From nobody Fri Sep 25 13:16:55 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) (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 D2F444A0924; Fri, 11 Sep 2026 21:39:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162801; cv=none; b=OBk6jql9N3s/VJ46aMw/i7vGMQ2wb+GuEauvM+D5R3iko+I972OqR/NKiSQoY372rtFxYZgmW8fHEnD8kvNL1xJndkhcmarlShbZDVmKC5hYleEjambUC879VMGqmtQ50SczH89tdfJlnQ8m5haWBLgCcW3bf65E4b7MrytNo1Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162801; c=relaxed/simple; bh=ETcu91PDs3gLxLnQuKEIAtZJFznbfQuLnFoKByW+LdE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=UXuT0O8XVcCuhqO96t9n/iMDv3MpTLkWZHsO73Q1u3Um4woZP5ei2uCBcoKUIz9b0tcuQPp5YJPsUIxIVZAullfiUz1C6YsH+kCNZsN4nvChFIyuYFtybiOsqbRzSGY6QTiRL82Q77v9wxY1NqLVaoloSGM4vAmy2yM6fTj4THk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=AeMm6AQZ; arc=none smtp.client-ip=192.198.163.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="AeMm6AQZ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789162799; x=1820698799; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ETcu91PDs3gLxLnQuKEIAtZJFznbfQuLnFoKByW+LdE=; b=AeMm6AQZbgMdX2G7ZfXPci+JvT4V3jUwop8K+WVHe0+tJystmLlOy8ZD zFE8YF83usgKneviSiG+sso6Ex3vP5icLTGWI1D36bZAWFsEj6pZZ5XiM aJNdRkrPeSKNdaKDNeK/uL+q12X0RWVoWPJy/J2fCPuTxOzWofWOo6e3F rBTQf3U3o5skkbANVABk1SH+XURGwrGV1URwk9EcSF8x+ebRv9U5pbL/j Dklc+3kMhoNbAfLL2fOh9fEpfB7VMjpj/UZbxAiKQthrAd23Mj5AaAbpO EfscaIeQ6c3wMT/Do1vgeIMxW0L6KrRbEdz8BBo0mmPv7rY6nq7/j4UyJ Q==; X-CSE-ConnectionGUID: 6nHdNOBtRmSsBEiYiEJE7Q== X-CSE-MsgGUID: TNCd9RNVRMiufQNOrGlJ5w== X-IronPort-AV: E=McAfee;i="6800,10657,11902"; a="88572369" X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="88572369" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Sep 2026 14:39:58 -0700 X-CSE-ConnectionGUID: bafdppx8Q3O48WoejAKV3w== X-CSE-MsgGUID: EhBRnRZEQcu+vT4F8WCjKw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="272003903" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa007.jf.intel.com with ESMTP; 11 Sep 2026 14:39:57 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Paolo Bonzini , Sean Christopherson , Jonathan Corbet , Shuah Khan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Xin Li , Andy Lutomirski , Peter Zijlstra , Andrew Cooper , Tom Lendacky , Nikunj A Dadhania , Shivansh Dhiman , David Woodhouse , Chao Gao , Binbin Wu , Sohil Mehta , Zhao Liu , Yosry Ahmed , David Matlack , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v10 01/28] KVM: VMX: Enable support for secondary VM exit controls Date: Fri, 11 Sep 2026 14:36:31 -0700 Message-ID: <20260911213659.2025974-2-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260911213659.2025974-1-sohil.mehta@intel.com> References: <20260911213659.2025974-1-sohil.mehta@intel.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 (Intel)" Introduce infrastructure to support secondary VM exit controls. Always load the controls when supported by hardware, though all control bits remain clear in this patch. Signed-off-by: Xin Li (Intel) Signed-off-by: Sohil Mehta --- v10: - No change --- arch/x86/include/asm/msr-index.h | 1 + arch/x86/include/asm/vmx.h | 3 +++ arch/x86/kvm/vmx/capabilities.h | 9 ++++++++- arch/x86/kvm/vmx/vmcs.h | 1 + arch/x86/kvm/vmx/vmx.c | 29 +++++++++++++++++++++++++++-- arch/x86/kvm/vmx/vmx.h | 7 ++++++- 6 files changed, 46 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-in= dex.h index 18c4be75e927..ad899d9070e1 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -1274,6 +1274,7 @@ #define MSR_IA32_VMX_TRUE_ENTRY_CTLS 0x00000490 #define MSR_IA32_VMX_VMFUNC 0x00000491 #define MSR_IA32_VMX_PROCBASED_CTLS3 0x00000492 +#define MSR_IA32_VMX_EXIT_CTLS2 0x00000493 =20 #define MSR_IA32_MCU_STAGING_MBOX_ADDR 0x000007a5 =20 diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h index 3f1b3096ff04..1f7cffc118bf 100644 --- a/arch/x86/include/asm/vmx.h +++ b/arch/x86/include/asm/vmx.h @@ -119,6 +119,7 @@ struct vmcs { #define VM_EXIT_CLEAR_IA32_RTIT_CTL 0x02000000 #define VM_EXIT_LOAD_CET_STATE 0x10000000 #define VM_EXIT_SAVE_IA32_PERF_GLOBAL_CTRL 0x40000000 +#define VM_EXIT_ACTIVATE_SECONDARY_CONTROLS 0x80000000 =20 #define VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR 0x00036dff =20 @@ -275,6 +276,8 @@ enum vmcs_field { SHARED_EPT_POINTER =3D 0x0000203C, PID_POINTER_TABLE =3D 0x00002042, PID_POINTER_TABLE_HIGH =3D 0x00002043, + SECONDARY_VM_EXIT_CONTROLS =3D 0x00002044, + SECONDARY_VM_EXIT_CONTROLS_HIGH =3D 0x00002045, GUEST_PHYSICAL_ADDRESS =3D 0x00002400, GUEST_PHYSICAL_ADDRESS_HIGH =3D 0x00002401, VMCS_LINK_POINTER =3D 0x00002800, diff --git a/arch/x86/kvm/vmx/capabilities.h b/arch/x86/kvm/vmx/capabilitie= s.h index 810119167f79..6be818ce27bf 100644 --- a/arch/x86/kvm/vmx/capabilities.h +++ b/arch/x86/kvm/vmx/capabilities.h @@ -57,8 +57,9 @@ struct vmcs_config { u32 cpu_based_exec_ctrl; u32 cpu_based_2nd_exec_ctrl; u64 cpu_based_3rd_exec_ctrl; - u32 vmexit_ctrl; u32 vmentry_ctrl; + u32 vmexit_ctrl; + u64 vmexit_2nd_ctrl; u64 misc; struct nested_vmx_msrs nested; }; @@ -149,6 +150,12 @@ static inline bool cpu_has_tertiary_exec_ctrls(void) CPU_BASED_ACTIVATE_TERTIARY_CONTROLS; } =20 +static inline bool cpu_has_secondary_vmexit_ctrls(void) +{ + return vmcs_config.vmexit_ctrl & + VM_EXIT_ACTIVATE_SECONDARY_CONTROLS; +} + static inline bool cpu_has_vmx_virtualize_apic_accesses(void) { return vmcs_config.cpu_based_2nd_exec_ctrl & diff --git a/arch/x86/kvm/vmx/vmcs.h b/arch/x86/kvm/vmx/vmcs.h index 1f16ddeae9cb..ca341c59bab1 100644 --- a/arch/x86/kvm/vmx/vmcs.h +++ b/arch/x86/kvm/vmx/vmcs.h @@ -45,6 +45,7 @@ struct vmcs_host_state { struct vmcs_controls_shadow { u32 vm_entry; u32 vm_exit; + u64 secondary_vm_exit; u32 pin; u32 exec; u32 secondary_exec; diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 504630f0eb40..b4aec4218b7d 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -2751,8 +2751,9 @@ static int setup_vmcs_config(struct vmcs_config *vmcs= _conf, u32 _cpu_based_exec_control =3D 0; u32 _cpu_based_2nd_exec_control =3D 0; u64 _cpu_based_3rd_exec_control =3D 0; - u32 _vmexit_control =3D 0; u32 _vmentry_control =3D 0; + u32 _vmexit_control =3D 0; + u64 _vmexit2_control =3D 0; u64 basic_msr; u64 misc_msr; =20 @@ -2773,6 +2774,12 @@ static int setup_vmcs_config(struct vmcs_config *vmc= s_conf, { VM_ENTRY_LOAD_CET_STATE, VM_EXIT_LOAD_CET_STATE }, }; =20 + struct { + u32 entry_control; + u64 exit_control; + } const vmcs_entry_exit2_pairs[] =3D { + }; + memset(vmcs_conf, 0, sizeof(*vmcs_conf)); =20 if (adjust_vmx_controls(KVM_REQUIRED_VMX_CPU_BASED_VM_EXEC_CONTROL, @@ -2870,10 +2877,19 @@ static int setup_vmcs_config(struct vmcs_config *vm= cs_conf, &_vmentry_control)) return -EIO; =20 + if (_vmexit_control & VM_EXIT_ACTIVATE_SECONDARY_CONTROLS) + _vmexit2_control =3D + adjust_vmx_controls64(KVM_OPTIONAL_VMX_SECONDARY_VM_EXIT_CONTROLS, + MSR_IA32_VMX_EXIT_CTLS2); + if (vmx_check_entry_exit_pairs(vmcs_entry_exit_pairs, _vmentry_control, _vmexit_control)) return -EIO; =20 + if (vmx_check_entry_exit_pairs(vmcs_entry_exit2_pairs, + _vmentry_control, _vmexit2_control)) + return -EIO; + /* * Some cpus support VM_{ENTRY,EXIT}_IA32_PERF_GLOBAL_CTRL but they * can't be used due to an errata where VM Exit may incorrectly clear @@ -2922,8 +2938,9 @@ static int setup_vmcs_config(struct vmcs_config *vmcs= _conf, vmcs_conf->cpu_based_exec_ctrl =3D _cpu_based_exec_control; vmcs_conf->cpu_based_2nd_exec_ctrl =3D _cpu_based_2nd_exec_control; vmcs_conf->cpu_based_3rd_exec_ctrl =3D _cpu_based_3rd_exec_control; - vmcs_conf->vmexit_ctrl =3D _vmexit_control; vmcs_conf->vmentry_ctrl =3D _vmentry_control; + vmcs_conf->vmexit_ctrl =3D _vmexit_control; + vmcs_conf->vmexit_2nd_ctrl =3D _vmexit2_control; vmcs_conf->misc =3D misc_msr; =20 #if IS_ENABLED(CONFIG_HYPERV) @@ -4617,6 +4634,11 @@ static u32 vmx_get_initial_vmexit_ctrl(void) VM_EXIT_SAVE_IA32_PERF_GLOBAL_CTRL); } =20 +static u64 vmx_secondary_vmexit_ctrl(void) +{ + return vmcs_config.vmexit_2nd_ctrl; +} + void vmx_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu) { struct vcpu_vmx *vmx =3D to_vmx(vcpu); @@ -4960,6 +4982,9 @@ static void init_vmcs(struct vcpu_vmx *vmx) =20 vm_exit_controls_set(vmx, vmx_get_initial_vmexit_ctrl()); =20 + if (cpu_has_secondary_vmexit_ctrls()) + secondary_vm_exit_controls_set(vmx, vmx_secondary_vmexit_ctrl()); + /* 22.2.1, 20.8.1 */ vm_entry_controls_set(vmx, vmx_get_initial_vmentry_ctrl()); =20 diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index dc8517f15bc4..6295f9302cd9 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -501,7 +501,11 @@ static inline u8 vmx_get_rvi(void) VM_EXIT_PT_CONCEAL_PIP | \ VM_EXIT_CLEAR_IA32_RTIT_CTL | \ VM_EXIT_LOAD_CET_STATE | \ - VM_EXIT_SAVE_IA32_PERF_GLOBAL_CTRL) + VM_EXIT_SAVE_IA32_PERF_GLOBAL_CTRL | \ + VM_EXIT_ACTIVATE_SECONDARY_CONTROLS) + +#define KVM_REQUIRED_VMX_SECONDARY_VM_EXIT_CONTROLS (0) +#define KVM_OPTIONAL_VMX_SECONDARY_VM_EXIT_CONTROLS (0) =20 #define KVM_REQUIRED_VMX_PIN_BASED_VM_EXEC_CONTROL \ (PIN_BASED_EXT_INTR_MASK | \ @@ -615,6 +619,7 @@ static __always_inline void lname##_controls_changebit(= struct vcpu_vmx *vmx, u## } BUILD_CONTROLS_SHADOW(vm_entry, VM_ENTRY_CONTROLS, 32) BUILD_CONTROLS_SHADOW(vm_exit, VM_EXIT_CONTROLS, 32) +BUILD_CONTROLS_SHADOW(secondary_vm_exit, SECONDARY_VM_EXIT_CONTROLS, 64) BUILD_CONTROLS_SHADOW(pin, PIN_BASED_VM_EXEC_CONTROL, 32) BUILD_CONTROLS_SHADOW(exec, CPU_BASED_VM_EXEC_CONTROL, 32) BUILD_CONTROLS_SHADOW(secondary_exec, SECONDARY_VM_EXEC_CONTROL, 32) --=20 2.43.0 From nobody Fri Sep 25 13:16:55 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) (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 BBAB348663E; Fri, 11 Sep 2026 21:40:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162809; cv=none; b=JVVJSDQVEOhpRIPJALezl1qACvYBWcctoSGYrZkprfvfj78jvJ6kzhwbdXUowXGi0ZBTYWbjozDJDxcbYFnpJ8rAn8AoUAoP1Y/eZ8Pe04JjU2U4ifev0RydfCIyTi4d/VAACjb3D07vB3rRGCYe6omgTbIvx2gC1b+lB1Evyi4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162809; c=relaxed/simple; bh=3JG819fFRjeED+8qgUp8I6kuFeMoUUV2wMY/qZYu45g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=UMawVTthwK6aF1Gsr9BXPkYoFRlbBxP+AKpZqmftl7HNISvlCUyh/Em8II45CkySPc7WgQ+3n9QUoESKLx+s5yWSba/kbxLj0J/LPGDdgJJBrVYf/1oQyNT32sGDVkOgt0wa9HYIR1jLdN6sra6KgIUxWI/6RfuTDTnW6MQIhas= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=Jp5uWYGq; arc=none smtp.client-ip=192.198.163.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="Jp5uWYGq" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789162808; x=1820698808; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=3JG819fFRjeED+8qgUp8I6kuFeMoUUV2wMY/qZYu45g=; b=Jp5uWYGqtyuKFQ1hD+ur7f+0cGMBPgEoHw2cQV5tqcpIWYlKRFu5kEVH Sy2Y+6i6KISx8pV4S7tk90zXFyNZBCFSIY/xLrxfDd0YEhjsEzX8cPCUX GAeE08+ozCThOsZFH48lbq7fy2Hx9uuCUilNQRLfBgUwlNvgIg3iiKvHH k54kgjMSoR6n4u1OPPt5aFPh49KgaZOdqYxKymtDjcw1VI2TyYJXNpm// 0wqa+3FmzgmuVN0+DgQDo7Oy6A4euvdziys10fjP5B8phH1aQj8nKSLFg 0erCMXqmV2G/DCC16EgF63VDSNQMgr32oV6uvO+N4A5/cKh/HlAYgpkmH Q==; X-CSE-ConnectionGUID: HbuFC2WMQFO+q6YCy+u6aQ== X-CSE-MsgGUID: tTwQxxhqQb2IF47s3DlNUg== X-IronPort-AV: E=McAfee;i="6800,10657,11902"; a="88572405" X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="88572405" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Sep 2026 14:40:07 -0700 X-CSE-ConnectionGUID: sJ+j2DymQ2qU7iCXcpGo3w== X-CSE-MsgGUID: 6pR1esIKQCeV++gA7bWxiw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="272003926" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa007.jf.intel.com with ESMTP; 11 Sep 2026 14:40:06 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Paolo Bonzini , Sean Christopherson , Jonathan Corbet , Shuah Khan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Xin Li , Andy Lutomirski , Peter Zijlstra , Andrew Cooper , Tom Lendacky , Nikunj A Dadhania , Shivansh Dhiman , David Woodhouse , Chao Gao , Binbin Wu , Sohil Mehta , Zhao Liu , Yosry Ahmed , David Matlack , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v10 02/28] KVM: VMX: Initialize VM entry/exit FRED controls in vmcs_config Date: Fri, 11 Sep 2026 14:36:32 -0700 Message-ID: <20260911213659.2025974-3-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260911213659.2025974-1-sohil.mehta@intel.com> References: <20260911213659.2025974-1-sohil.mehta@intel.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 (Intel)" Setup VM entry/exit FRED controls in the global vmcs_config for proper FRED VMCS fields management: 1) load guest FRED state upon VM entry. 2) save guest FRED state during VM exit. 3) load host FRED state during VM exit. Also add FRED control consistency checks to the existing VM entry/exit consistency check framework. Signed-off-by: Xin Li (Intel) Signed-off-by: Sohil Mehta Reviewed-by: Chao Gao Reviewed-by: Binbin Wu --- v10: - No change --- arch/x86/include/asm/vmx.h | 4 ++++ arch/x86/kvm/vmx/vmx.c | 2 ++ arch/x86/kvm/vmx/vmx.h | 7 +++++-- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h index 1f7cffc118bf..682f09933612 100644 --- a/arch/x86/include/asm/vmx.h +++ b/arch/x86/include/asm/vmx.h @@ -121,6 +121,9 @@ struct vmcs { #define VM_EXIT_SAVE_IA32_PERF_GLOBAL_CTRL 0x40000000 #define VM_EXIT_ACTIVATE_SECONDARY_CONTROLS 0x80000000 =20 +#define SECONDARY_VM_EXIT_SAVE_IA32_FRED BIT_ULL(0) +#define SECONDARY_VM_EXIT_LOAD_IA32_FRED BIT_ULL(1) + #define VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR 0x00036dff =20 #define VM_ENTRY_LOAD_DEBUG_CONTROLS 0x00000004 @@ -134,6 +137,7 @@ struct vmcs { #define VM_ENTRY_PT_CONCEAL_PIP 0x00020000 #define VM_ENTRY_LOAD_IA32_RTIT_CTL 0x00040000 #define VM_ENTRY_LOAD_CET_STATE 0x00100000 +#define VM_ENTRY_LOAD_IA32_FRED 0x00800000 =20 #define VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR 0x000011ff =20 diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index b4aec4218b7d..062631e2dd37 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -2778,6 +2778,8 @@ static int setup_vmcs_config(struct vmcs_config *vmcs= _conf, u32 entry_control; u64 exit_control; } const vmcs_entry_exit2_pairs[] =3D { + { VM_ENTRY_LOAD_IA32_FRED, + SECONDARY_VM_EXIT_SAVE_IA32_FRED | SECONDARY_VM_EXIT_LOAD_IA32_FRED }, }; =20 memset(vmcs_conf, 0, sizeof(*vmcs_conf)); diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index 6295f9302cd9..7a22e1b1a273 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -477,7 +477,8 @@ static inline u8 vmx_get_rvi(void) VM_ENTRY_LOAD_BNDCFGS | \ VM_ENTRY_PT_CONCEAL_PIP | \ VM_ENTRY_LOAD_IA32_RTIT_CTL | \ - VM_ENTRY_LOAD_CET_STATE) + VM_ENTRY_LOAD_CET_STATE | \ + VM_ENTRY_LOAD_IA32_FRED) =20 #define __KVM_REQUIRED_VMX_VM_EXIT_CONTROLS \ (VM_EXIT_SAVE_DEBUG_CONTROLS | \ @@ -505,7 +506,9 @@ static inline u8 vmx_get_rvi(void) VM_EXIT_ACTIVATE_SECONDARY_CONTROLS) =20 #define KVM_REQUIRED_VMX_SECONDARY_VM_EXIT_CONTROLS (0) -#define KVM_OPTIONAL_VMX_SECONDARY_VM_EXIT_CONTROLS (0) +#define KVM_OPTIONAL_VMX_SECONDARY_VM_EXIT_CONTROLS \ + (SECONDARY_VM_EXIT_SAVE_IA32_FRED | \ + SECONDARY_VM_EXIT_LOAD_IA32_FRED) =20 #define KVM_REQUIRED_VMX_PIN_BASED_VM_EXEC_CONTROL \ (PIN_BASED_EXT_INTR_MASK | \ --=20 2.43.0 From nobody Fri Sep 25 13:16:55 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) (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 68DFC4570D1; Fri, 11 Sep 2026 21:40:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162818; cv=none; b=FxZAQXnzvBObwj4YrHa7IhggJ6jW2fYs7Q/uJSVjoYthrvjxt79eJY4aa2fcTxGC5ejISdxrP24YXZb2WIKrq52iYQ8PNnI2tf2pZdtjncp0llBUKTLUknjyPIQbZpLsL0SFfQw20r6LLiuOQyR7mtJLErbf3hvRYGLW9aCfLLg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162818; c=relaxed/simple; bh=Rei04Ot5HKLPhTtYmF1FETakMjgMhAt/5SlhNx5l7Iw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fJ/+1GHnqULj01UJV8FTMzE9Qeg5OHxuWw02uOMgDxVcvB5+E1JmEKE36pY7shFvSwpcjLKcyGwdbAuynkKJoi4e/t7vOG3pHhxXv16YifhPkMTpY9h6F24dUu23TbGPRxaADfCf0qP+M/+3lih8bjs3uN/fKxcm6ngEdWZoi5o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=PR/WsRUP; arc=none smtp.client-ip=192.198.163.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="PR/WsRUP" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789162817; x=1820698817; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Rei04Ot5HKLPhTtYmF1FETakMjgMhAt/5SlhNx5l7Iw=; b=PR/WsRUPeDKVUa3fY3Icn4gWQ1+I264F7E7sZIjy9bL/R6yxuqGvw3yY sx5XQ1onj0p46eM1VV85hL3VQsBBVlI4dV5RnQS4UVO9KGDieT37wgRQS yuVPjjwDPo9DcTQ0Jo2FzMpijDrnyLtV4J01yJf0HVDzSKZQrUJErRD88 lDiUaoVj1QAvY3AbElKisZsdDNQSXhNL9X9U5kX8THpTgu2+WmgeiUGvQ qmjlygr+7ukEgPus/ci6LYBOXuP9tEnUd99UB4MzbeqtPTqILPi/GKDur 6fT6qT/P10zVZeCzvtsDa0Y2F2fwQEn9+lLeZaXDYXcviwaxPgMk842W8 g==; X-CSE-ConnectionGUID: 8bT8SIvnSRm6T79FjyMe6Q== X-CSE-MsgGUID: mYoo3BaQSm+mkTKF34PaVA== X-IronPort-AV: E=McAfee;i="6800,10657,11902"; a="88572420" X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="88572420" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Sep 2026 14:40:16 -0700 X-CSE-ConnectionGUID: lBeSR+TGSnC/g3LiNCLqag== X-CSE-MsgGUID: QNTjwgZSQASxf7lp9wD0Vg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="272003935" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa007.jf.intel.com with ESMTP; 11 Sep 2026 14:40:15 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Paolo Bonzini , Sean Christopherson , Jonathan Corbet , Shuah Khan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Xin Li , Andy Lutomirski , Peter Zijlstra , Andrew Cooper , Tom Lendacky , Nikunj A Dadhania , Shivansh Dhiman , David Woodhouse , Chao Gao , Binbin Wu , Sohil Mehta , Zhao Liu , Yosry Ahmed , David Matlack , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v10 03/28] KVM: VMX: Disable FRED if FRED consistency checks fail Date: Fri, 11 Sep 2026 14:36:33 -0700 Message-ID: <20260911213659.2025974-4-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260911213659.2025974-1-sohil.mehta@intel.com> References: <20260911213659.2025974-1-sohil.mehta@intel.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 (Intel)" Do not virtualize FRED if FRED consistency checks fail. Either on broken hardware, or when run KVM on top of another hypervisor before the underlying hypervisor implements nested FRED correctly. Suggested-by: Chao Gao Signed-off-by: Xin Li (Intel) Signed-off-by: Sohil Mehta Reviewed-by: Chao Gao --- v10: - Remove the comment about why not check FRED VM-exit controls in cpu_has_vmx_fred() (Sean). - Remove redundant parentheses (Sean). --- arch/x86/kvm/vmx/capabilities.h | 5 +++++ arch/x86/kvm/vmx/vmx.c | 3 +++ 2 files changed, 8 insertions(+) diff --git a/arch/x86/kvm/vmx/capabilities.h b/arch/x86/kvm/vmx/capabilitie= s.h index 6be818ce27bf..95d22a54f856 100644 --- a/arch/x86/kvm/vmx/capabilities.h +++ b/arch/x86/kvm/vmx/capabilities.h @@ -409,6 +409,11 @@ static inline bool vmx_pebs_supported(void) !enable_mediated_pmu; } =20 +static inline bool cpu_has_vmx_fred(void) +{ + return vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_FRED; +} + static inline bool cpu_has_notify_vmexit(void) { return vmcs_config.cpu_based_2nd_exec_ctrl & diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 062631e2dd37..2a2218e0983b 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -8122,6 +8122,9 @@ static __init void vmx_set_cpu_caps(void) kvm_cpu_cap_check_and_set(X86_FEATURE_DTES64); } =20 + if (!cpu_has_vmx_fred()) + kvm_cpu_cap_clear(X86_FEATURE_FRED); + if (!enable_pmu) kvm_cpu_cap_clear(X86_FEATURE_PDCM); kvm_caps.supported_perf_cap =3D vmx_get_perf_capabilities(); --=20 2.43.0 From nobody Fri Sep 25 13:16:55 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) (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 4327130EF92; Fri, 11 Sep 2026 21:40:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162828; cv=none; b=tvERtwPq7PpodxBcL4gfK98SRyKcynZLK0bnuBZuJrtSYXGQ6Z16eJic/8c5I8PQ7fQqpDxzpwPOpo049nRRpJ5cBSqKoJncNwagokZp4jxSjnL+X69ZA6caLpco9Oiuw6glOvHuX6uXQDDadQv1K+SwdpngW8kdkeT0S+z4ufs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162828; c=relaxed/simple; bh=iwxzmH2iihIdxmWRlG66weRogxbaF6jOqwKQ+MUSomg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=i8IN93VD24CIcjEcUB9E8HOwR8IDTL+IpC8X7/sx54O9OdEvVgP427pp0r4DN04Hd2Jt39vVtRsij1XPvkCvdkr9ym883LpNllNY5k3AWuOQ07jWq+IAxOF39kyLNMh5uJcJG2vgc4N86pkjYMfhynck9m8cjTlqyEpXcVGxZig= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=QZDc4pF4; arc=none smtp.client-ip=192.198.163.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="QZDc4pF4" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789162826; x=1820698826; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=iwxzmH2iihIdxmWRlG66weRogxbaF6jOqwKQ+MUSomg=; b=QZDc4pF4jORHItwb0yKyxClFNk2CfRlJ+gu1h6q0M+cb1zTRVttuEYUL BIK2nx4almUTuvlor9aizqAlKTcnQR5RbMmw1/2Xvxp7j+UODwmeaE+WG c3Yxyd4o6Qno5MepG4xF7HcryBMhMo4mSLThebCjry0avkbfPLNetLJkp Q2p/fUfgthBnwdPafSf2WiKadyWC6V+Y2hOGDQ8uibyZD5hlvgoT36BBb FSeQer0uWGmIQGLF1nPkjmaHfKMXOeNk/pz5alb8cddeXFnALSmkXY/3d cvTYm3emhBssPve4mFtdfdAAaqUe7I6EfTY8+2OVJptyMKIVvXYgMDQdq w==; X-CSE-ConnectionGUID: EBuzjFpxQq+8PB4NW925Ww== X-CSE-MsgGUID: xITvrzZZRaWsUw+2wUjFYw== X-IronPort-AV: E=McAfee;i="6800,10657,11902"; a="88572454" X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="88572454" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Sep 2026 14:40:26 -0700 X-CSE-ConnectionGUID: Zx4jX7Y9RVSk51JgqfnD6A== X-CSE-MsgGUID: 9k7Bz6UBSBGNtPMZSs8tvg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="272003956" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa007.jf.intel.com with ESMTP; 11 Sep 2026 14:40:25 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Paolo Bonzini , Sean Christopherson , Jonathan Corbet , Shuah Khan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Xin Li , Andy Lutomirski , Peter Zijlstra , Andrew Cooper , Tom Lendacky , Nikunj A Dadhania , Shivansh Dhiman , David Woodhouse , Chao Gao , Binbin Wu , Sohil Mehta , Zhao Liu , Yosry Ahmed , David Matlack , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v10 04/28] x86/cea: Prefix event stack names with ESTACK_ Date: Fri, 11 Sep 2026 14:36:34 -0700 Message-ID: <20260911213659.2025974-5-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260911213659.2025974-1-sohil.mehta@intel.com> References: <20260911213659.2025974-1-sohil.mehta@intel.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 (Intel)" Add the ESTACK_ prefix to event stack names to improve clarity and readability. Without the prefix, names like DF, NMI, and DB are too brief and potentially ambiguous. This renaming also prepares for converting __this_cpu_ist_top_va from a macro into a function that accepts an enum exception_stack_ordering argument, without requiring changes to existing callsites. Signed-off-by: Xin Li (Intel) Signed-off-by: Sohil Mehta Acked-by: Dave Hansen --- v10: - No change --- arch/x86/coco/sev/noinstr.c | 4 ++-- arch/x86/coco/sev/vc-handle.c | 2 +- arch/x86/include/asm/cpu_entry_area.h | 26 +++++++++++++------------- arch/x86/kernel/cpu/common.c | 10 +++++----- arch/x86/kernel/dumpstack_64.c | 14 +++++++------- arch/x86/kernel/fred.c | 6 +++--- arch/x86/kernel/traps.c | 2 +- arch/x86/mm/cpu_entry_area.c | 12 ++++++------ arch/x86/mm/fault.c | 2 +- 9 files changed, 39 insertions(+), 39 deletions(-) diff --git a/arch/x86/coco/sev/noinstr.c b/arch/x86/coco/sev/noinstr.c index e1e03f12fc7b..8a695ab67821 100644 --- a/arch/x86/coco/sev/noinstr.c +++ b/arch/x86/coco/sev/noinstr.c @@ -31,7 +31,7 @@ static __always_inline bool on_vc_stack(struct pt_regs *r= egs) if (ip_within_syscall_gap(regs)) return false; =20 - return ((sp >=3D __this_cpu_ist_bottom_va(VC)) && (sp < __this_cpu_ist_to= p_va(VC))); + return ((sp >=3D __this_cpu_ist_bottom_va(ESTACK_VC)) && (sp < __this_cpu= _ist_top_va(ESTACK_VC))); } =20 /* @@ -83,7 +83,7 @@ void noinstr __sev_es_ist_exit(void) /* Read IST entry */ ist =3D __this_cpu_read(cpu_tss_rw.x86_tss.ist[IST_INDEX_VC]); =20 - if (WARN_ON(ist =3D=3D __this_cpu_ist_top_va(VC))) + if (WARN_ON(ist =3D=3D __this_cpu_ist_top_va(ESTACK_VC))) return; =20 /* Read back old IST entry and write it to the TSS */ diff --git a/arch/x86/coco/sev/vc-handle.c b/arch/x86/coco/sev/vc-handle.c index 96b62b49b2b5..134c14b489ef 100644 --- a/arch/x86/coco/sev/vc-handle.c +++ b/arch/x86/coco/sev/vc-handle.c @@ -871,7 +871,7 @@ static enum es_result vc_handle_exitcode(struct es_em_c= txt *ctxt, =20 static __always_inline bool is_vc2_stack(unsigned long sp) { - return (sp >=3D __this_cpu_ist_bottom_va(VC2) && sp < __this_cpu_ist_top_= va(VC2)); + return (sp >=3D __this_cpu_ist_bottom_va(ESTACK_VC2) && sp < __this_cpu_i= st_top_va(ESTACK_VC2)); } =20 static __always_inline bool vc_from_invalid_context(struct pt_regs *regs) diff --git a/arch/x86/include/asm/cpu_entry_area.h b/arch/x86/include/asm/c= pu_entry_area.h index 462fc34f1317..d0f884c28178 100644 --- a/arch/x86/include/asm/cpu_entry_area.h +++ b/arch/x86/include/asm/cpu_entry_area.h @@ -18,19 +18,19 @@ =20 /* Macro to enforce the same ordering and stack sizes */ #define ESTACKS_MEMBERS(guardsize, optional_stack_size) \ - char DF_stack_guard[guardsize]; \ - char DF_stack[EXCEPTION_STKSZ]; \ - char NMI_stack_guard[guardsize]; \ - char NMI_stack[EXCEPTION_STKSZ]; \ - char DB_stack_guard[guardsize]; \ - char DB_stack[EXCEPTION_STKSZ]; \ - char MCE_stack_guard[guardsize]; \ - char MCE_stack[EXCEPTION_STKSZ]; \ - char VC_stack_guard[guardsize]; \ - char VC_stack[optional_stack_size]; \ - char VC2_stack_guard[guardsize]; \ - char VC2_stack[optional_stack_size]; \ - char IST_top_guard[guardsize]; \ + char ESTACK_DF_stack_guard[guardsize]; \ + char ESTACK_DF_stack[EXCEPTION_STKSZ]; \ + char ESTACK_NMI_stack_guard[guardsize]; \ + char ESTACK_NMI_stack[EXCEPTION_STKSZ]; \ + char ESTACK_DB_stack_guard[guardsize]; \ + char ESTACK_DB_stack[EXCEPTION_STKSZ]; \ + char ESTACK_MCE_stack_guard[guardsize]; \ + char ESTACK_MCE_stack[EXCEPTION_STKSZ]; \ + char ESTACK_VC_stack_guard[guardsize]; \ + char ESTACK_VC_stack[optional_stack_size]; \ + char ESTACK_VC2_stack_guard[guardsize]; \ + char ESTACK_VC2_stack[optional_stack_size]; \ + char ESTACK_IST_top_guard[guardsize]; \ =20 /* The exception stacks' physical storage. No guard pages required */ struct exception_stacks { diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index a3df21d26460..99ec284fb829 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -2372,12 +2372,12 @@ static inline void setup_getcpu(int cpu) static inline void tss_setup_ist(struct tss_struct *tss) { /* Set up the per-CPU TSS IST stacks */ - tss->x86_tss.ist[IST_INDEX_DF] =3D __this_cpu_ist_top_va(DF); - tss->x86_tss.ist[IST_INDEX_NMI] =3D __this_cpu_ist_top_va(NMI); - tss->x86_tss.ist[IST_INDEX_DB] =3D __this_cpu_ist_top_va(DB); - tss->x86_tss.ist[IST_INDEX_MCE] =3D __this_cpu_ist_top_va(MCE); + tss->x86_tss.ist[IST_INDEX_DF] =3D __this_cpu_ist_top_va(ESTACK_DF); + tss->x86_tss.ist[IST_INDEX_NMI] =3D __this_cpu_ist_top_va(ESTACK_NMI); + tss->x86_tss.ist[IST_INDEX_DB] =3D __this_cpu_ist_top_va(ESTACK_DB); + tss->x86_tss.ist[IST_INDEX_MCE] =3D __this_cpu_ist_top_va(ESTACK_MCE); /* Only mapped when SEV-ES is active */ - tss->x86_tss.ist[IST_INDEX_VC] =3D __this_cpu_ist_top_va(VC); + tss->x86_tss.ist[IST_INDEX_VC] =3D __this_cpu_ist_top_va(ESTACK_VC); } #else /* CONFIG_X86_64 */ static inline void tss_setup_ist(struct tss_struct *tss) { } diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c index 6c5defd6569a..40f51e278171 100644 --- a/arch/x86/kernel/dumpstack_64.c +++ b/arch/x86/kernel/dumpstack_64.c @@ -73,7 +73,7 @@ struct estack_pages { PFN_DOWN(CEA_ESTACK_OFFS(st) + CEA_ESTACK_SIZE(st) - 1)] =3D { \ .offs =3D CEA_ESTACK_OFFS(st), \ .size =3D CEA_ESTACK_SIZE(st), \ - .type =3D STACK_TYPE_EXCEPTION + ESTACK_ ##st, } + .type =3D STACK_TYPE_EXCEPTION + st, } =20 /* * Array of exception stack page descriptors. If the stack is larger than @@ -83,12 +83,12 @@ struct estack_pages { */ static const struct estack_pages estack_pages[CEA_ESTACK_PAGES] ____cacheline_aligned = =3D { - EPAGERANGE(DF), - EPAGERANGE(NMI), - EPAGERANGE(DB), - EPAGERANGE(MCE), - EPAGERANGE(VC), - EPAGERANGE(VC2), + EPAGERANGE(ESTACK_DF), + EPAGERANGE(ESTACK_NMI), + EPAGERANGE(ESTACK_DB), + EPAGERANGE(ESTACK_MCE), + EPAGERANGE(ESTACK_VC), + EPAGERANGE(ESTACK_VC2), }; =20 static __always_inline bool in_exception_stack(unsigned long *stack, struc= t stack_info *info) diff --git a/arch/x86/kernel/fred.c b/arch/x86/kernel/fred.c index 117aa06d25ca..1c452a389a70 100644 --- a/arch/x86/kernel/fred.c +++ b/arch/x86/kernel/fred.c @@ -84,7 +84,7 @@ void cpu_init_fred_rsps(void) FRED_STKLVL(X86_TRAP_DF, FRED_DF_STACK_LEVEL)); =20 /* The FRED equivalents to IST stacks... */ - wrmsrq(MSR_IA32_FRED_RSP1, __this_cpu_ist_top_va(DB)); - wrmsrq(MSR_IA32_FRED_RSP2, __this_cpu_ist_top_va(NMI)); - wrmsrq(MSR_IA32_FRED_RSP3, __this_cpu_ist_top_va(DF)); + wrmsrq(MSR_IA32_FRED_RSP1, __this_cpu_ist_top_va(ESTACK_DB)); + wrmsrq(MSR_IA32_FRED_RSP2, __this_cpu_ist_top_va(ESTACK_NMI)); + wrmsrq(MSR_IA32_FRED_RSP3, __this_cpu_ist_top_va(ESTACK_DF)); } diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 30aa8369957e..8afd607a5873 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -1075,7 +1075,7 @@ asmlinkage __visible noinstr struct pt_regs *vc_switc= h_off_ist(struct pt_regs *r =20 if (!get_stack_info_noinstr(stack, current, &info) || info.type =3D=3D ST= ACK_TYPE_ENTRY || info.type > STACK_TYPE_EXCEPTION_LAST) - sp =3D __this_cpu_ist_top_va(VC2); + sp =3D __this_cpu_ist_top_va(ESTACK_VC2); =20 sync: /* diff --git a/arch/x86/mm/cpu_entry_area.c b/arch/x86/mm/cpu_entry_area.c index 575f863f3c75..9fa371af8abc 100644 --- a/arch/x86/mm/cpu_entry_area.c +++ b/arch/x86/mm/cpu_entry_area.c @@ -151,15 +151,15 @@ static void __init percpu_setup_exception_stacks(unsi= gned int cpu) * by guard pages so each stack must be mapped separately. DB2 is * not mapped; it just exists to catch triple nesting of #DB. */ - cea_map_stack(DF); - cea_map_stack(NMI); - cea_map_stack(DB); - cea_map_stack(MCE); + cea_map_stack(ESTACK_DF); + cea_map_stack(ESTACK_NMI); + cea_map_stack(ESTACK_DB); + cea_map_stack(ESTACK_MCE); =20 if (IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT)) { if (cc_platform_has(CC_ATTR_GUEST_STATE_ENCRYPT)) { - cea_map_stack(VC); - cea_map_stack(VC2); + cea_map_stack(ESTACK_VC); + cea_map_stack(ESTACK_VC2); } } } diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 45b99c3b1442..f6ee1cc3f125 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -677,7 +677,7 @@ page_fault_oops(struct pt_regs *regs, unsigned long err= or_code, * and then double-fault, though, because we're likely to * break the console driver and lose most of the stack dump. */ - call_on_stack(__this_cpu_ist_top_va(DF) - sizeof(void*), + call_on_stack(__this_cpu_ist_top_va(ESTACK_DF) - sizeof(void*), handle_stack_overflow, ASM_CALL_ARG3, , [arg1] "r" (regs), [arg2] "r" (address), [arg3] "r" (&info)); --=20 2.43.0 From nobody Fri Sep 25 13:16:55 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) (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 2CD5F486431; Fri, 11 Sep 2026 21:40:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162837; cv=none; b=RP9DsMLsXD1A3FWCubxFpGvFr2j5vrsQSJsBD6IrevgZ3ts4vR7pgox1Lj5hSjba5edNTPclh1moeOrmpCB+yjG/wFPeaxqOZQjFvC6eJl1V7pd+uPnF3XwjbUKj3BMFdGR0k8BRL65snlSAvWJcdEBWZGNubVH3S8ElZwqFmls= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162837; c=relaxed/simple; bh=GrFbnV7U/VzUxcfB10Sq6sd5UMQx0UKgx6eLIPtlYPU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mxJ/wY6BBhr8smBENXV72axkbPOyyeL0IW4V4e654lPR/xmjEyeEIqWJG/Ld6ukVd9ytjrudlXA3ANXg8VpRWxGyHvS3M0P6tIfpJjt2ZwNsZd8vCVLbRnJRfgRJ2imhJUpNX2RXblqM8vmJuT++czwKUbOqA9BNdqn7xg/UVTc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=HXxXXw9X; arc=none smtp.client-ip=192.198.163.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="HXxXXw9X" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789162835; x=1820698835; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=GrFbnV7U/VzUxcfB10Sq6sd5UMQx0UKgx6eLIPtlYPU=; b=HXxXXw9Xs/ZVkH/Brcu2n3BwiIJ2cwpYA6wqdFMlgM31+FYAUdNfgsqe +Ox8rRdcBLTsFqz7wmGdvHt+d7uPD3cV2Djvy6ePm90RakK+UZqXNb4Ar 92prs7Tr03trn8lMV+U/oxAbP5llMMqonlTecaP2gKDdVB/LBs8j+nj+i 7EPev6d9OOnXyDsezZ9TOF5+Stigeawg7ula68uo5Aw+99HGYtl9/v+Ot EjahTm3CfUB6eyw3SVpljBMr78quGbzPT77AZTuo7vWwHcqMcsN2YVr7p wySC8Y6mtnJlxPhCSGqLg7yT+tSrIpLQpmZ9AEGUe/2npLi6WnS56ZvbO Q==; X-CSE-ConnectionGUID: mrIUKlG8TW6TwVkzOSPNyQ== X-CSE-MsgGUID: uMZdbgSCSOKDlzVum+Gclg== X-IronPort-AV: E=McAfee;i="6800,10657,11902"; a="88572468" X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="88572468" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Sep 2026 14:40:34 -0700 X-CSE-ConnectionGUID: e718XIOpSsu3rVM5kUdI0g== X-CSE-MsgGUID: wmeAbYCiSgCsu98P0SiNnA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="272003989" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa007.jf.intel.com with ESMTP; 11 Sep 2026 14:40:33 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Paolo Bonzini , Sean Christopherson , Jonathan Corbet , Shuah Khan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Xin Li , Andy Lutomirski , Peter Zijlstra , Andrew Cooper , Tom Lendacky , Nikunj A Dadhania , Shivansh Dhiman , David Woodhouse , Chao Gao , Binbin Wu , Sohil Mehta , Zhao Liu , Yosry Ahmed , David Matlack , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v10 05/28] x86/cea: Use array indexing to simplify exception stack access Date: Fri, 11 Sep 2026 14:36:35 -0700 Message-ID: <20260911213659.2025974-6-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260911213659.2025974-1-sohil.mehta@intel.com> References: <20260911213659.2025974-1-sohil.mehta@intel.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 (Intel)" Refactor struct cea_exception_stacks to leverage array indexing for exception stack access, improving code clarity and eliminating the need for the ESTACKS_MEMBERS() macro. Convert __this_cpu_ist_{bottom,top}_va() from macros to functions, allowing removal of the now-obsolete CEA_ESTACK_BOT and CEA_ESTACK_TOP macros. Also drop CEA_ESTACK_SIZE, which just duplicated EXCEPTION_STKSZ. Signed-off-by: Xin Li (Intel) Signed-off-by: Sohil Mehta Acked-by: Dave Hansen --- v10: - Check if the stack argument is within the array bounds of event_stacks (Boris). v9: - Refactor first and then export in a separate patch (Dave Hansen). --- arch/x86/include/asm/cpu_entry_area.h | 52 ++++++++++++--------------- arch/x86/kernel/dumpstack_64.c | 4 +-- arch/x86/mm/cpu_entry_area.c | 22 +++++++++++- 3 files changed, 45 insertions(+), 33 deletions(-) diff --git a/arch/x86/include/asm/cpu_entry_area.h b/arch/x86/include/asm/c= pu_entry_area.h index d0f884c28178..509e52fc3a0f 100644 --- a/arch/x86/include/asm/cpu_entry_area.h +++ b/arch/x86/include/asm/cpu_entry_area.h @@ -16,6 +16,19 @@ #define VC_EXCEPTION_STKSZ 0 #endif =20 +/* + * The exception stack ordering in [cea_]exception_stacks + */ +enum exception_stack_ordering { + ESTACK_DF, + ESTACK_NMI, + ESTACK_DB, + ESTACK_MCE, + ESTACK_VC, + ESTACK_VC2, + N_EXCEPTION_STACKS +}; + /* Macro to enforce the same ordering and stack sizes */ #define ESTACKS_MEMBERS(guardsize, optional_stack_size) \ char ESTACK_DF_stack_guard[guardsize]; \ @@ -39,37 +52,22 @@ struct exception_stacks { =20 /* The effective cpu entry area mapping with guard pages. */ struct cea_exception_stacks { - ESTACKS_MEMBERS(PAGE_SIZE, EXCEPTION_STKSZ) + struct { + char stack_guard[PAGE_SIZE]; + char stack[EXCEPTION_STKSZ]; + } event_stacks[N_EXCEPTION_STACKS]; + char IST_top_guard[PAGE_SIZE]; }; =20 -/* - * The exception stack ordering in [cea_]exception_stacks - */ -enum exception_stack_ordering { - ESTACK_DF, - ESTACK_NMI, - ESTACK_DB, - ESTACK_MCE, - ESTACK_VC, - ESTACK_VC2, - N_EXCEPTION_STACKS -}; - -#define CEA_ESTACK_SIZE(st) \ - sizeof(((struct cea_exception_stacks *)0)->st## _stack) - -#define CEA_ESTACK_BOT(ceastp, st) \ - ((unsigned long)&(ceastp)->st## _stack) - -#define CEA_ESTACK_TOP(ceastp, st) \ - (CEA_ESTACK_BOT(ceastp, st) + CEA_ESTACK_SIZE(st)) - #define CEA_ESTACK_OFFS(st) \ - offsetof(struct cea_exception_stacks, st## _stack) + offsetof(struct cea_exception_stacks, event_stacks[st].stack) =20 #define CEA_ESTACK_PAGES \ (sizeof(struct cea_exception_stacks) / PAGE_SIZE) =20 +extern unsigned long __this_cpu_ist_top_va(enum exception_stack_ordering s= tack); +extern unsigned long __this_cpu_ist_bottom_va(enum exception_stack_orderin= g stack); + #endif =20 #ifdef CONFIG_X86_32 @@ -144,10 +142,4 @@ static __always_inline struct entry_stack *cpu_entry_s= tack(int cpu) return &get_cpu_entry_area(cpu)->entry_stack_page.stack; } =20 -#define __this_cpu_ist_top_va(name) \ - CEA_ESTACK_TOP(__this_cpu_read(cea_exception_stacks), name) - -#define __this_cpu_ist_bottom_va(name) \ - CEA_ESTACK_BOT(__this_cpu_read(cea_exception_stacks), name) - #endif diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c index 40f51e278171..93b10b264e53 100644 --- a/arch/x86/kernel/dumpstack_64.c +++ b/arch/x86/kernel/dumpstack_64.c @@ -70,9 +70,9 @@ struct estack_pages { =20 #define EPAGERANGE(st) \ [PFN_DOWN(CEA_ESTACK_OFFS(st)) ... \ - PFN_DOWN(CEA_ESTACK_OFFS(st) + CEA_ESTACK_SIZE(st) - 1)] =3D { \ + PFN_DOWN(CEA_ESTACK_OFFS(st) + EXCEPTION_STKSZ - 1)] =3D { \ .offs =3D CEA_ESTACK_OFFS(st), \ - .size =3D CEA_ESTACK_SIZE(st), \ + .size =3D EXCEPTION_STKSZ, \ .type =3D STACK_TYPE_EXCEPTION + st, } =20 /* diff --git a/arch/x86/mm/cpu_entry_area.c b/arch/x86/mm/cpu_entry_area.c index 9fa371af8abc..a47dfd686bd3 100644 --- a/arch/x86/mm/cpu_entry_area.c +++ b/arch/x86/mm/cpu_entry_area.c @@ -18,6 +18,26 @@ static DEFINE_PER_CPU_PAGE_ALIGNED(struct entry_stack_pa= ge, entry_stack_storage) static DEFINE_PER_CPU_PAGE_ALIGNED(struct exception_stacks, exception_stac= ks); DEFINE_PER_CPU(struct cea_exception_stacks*, cea_exception_stacks); =20 +/* + * Typically invoked by entry code, so must be noinstr. + */ +noinstr unsigned long __this_cpu_ist_bottom_va(enum exception_stack_orderi= ng stack) +{ + struct cea_exception_stacks *s; + + BUILD_BUG_ON(ESTACK_DF !=3D 0); + BUG_ON(stack >=3D N_EXCEPTION_STACKS); + + s =3D __this_cpu_read(cea_exception_stacks); + + return (unsigned long)&s->event_stacks[stack].stack; +} + +noinstr unsigned long __this_cpu_ist_top_va(enum exception_stack_ordering = stack) +{ + return __this_cpu_ist_bottom_va(stack) + EXCEPTION_STKSZ; +} + static DEFINE_PER_CPU_READ_MOSTLY(unsigned long, _cea_offset); =20 static __always_inline unsigned int cea_offset(unsigned int cpu) @@ -132,7 +152,7 @@ static void __init percpu_setup_debug_store(unsigned in= t cpu) =20 #define cea_map_stack(name) do { \ npages =3D sizeof(estacks->name## _stack) / PAGE_SIZE; \ - cea_map_percpu_pages(cea->estacks.name## _stack, \ + cea_map_percpu_pages(cea->estacks.event_stacks[name].stack, \ estacks->name## _stack, npages, PAGE_KERNEL); \ } while (0) =20 --=20 2.43.0 From nobody Fri Sep 25 13:16:55 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) (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 367524A0F0F; Fri, 11 Sep 2026 21:40:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162844; cv=none; b=tL8GJ05X42Gf0i65h6JypTMKy4ts+4ZZ3rHDx05yD4uGksxE+vC4r7kWSfN6lLZgeilKecUXECPF18LZAyCUDM4+1gJpUGFWDfe+TptlxcfVBSt8JHjKYcTgbSOe/0JkZTWivs+NSXgN+Vebsyyok3su8W3WxB9JvtSVRLig5UY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162844; c=relaxed/simple; bh=w6qxiFwdlREk3h/Q9LuqQ/wTCx279xrP36NXKR5c2R0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=a5jgXCV/DcnvMryn4hquOcJtljTUmt8owgAsS5bNGLjUw+xDLeWwcTATmuC3e49kzqVFVRk7MfFdZ3YfdHReZ7V6v19x3r342IqjNtNKKBiAhH6QPrm0aEK71Qs63GJDbntO6cj7WjkAfhL7gd3dVJr7CU6hNkUJtMZotybvkqc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=UM9L0qJ8; arc=none smtp.client-ip=192.198.163.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="UM9L0qJ8" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789162842; x=1820698842; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=w6qxiFwdlREk3h/Q9LuqQ/wTCx279xrP36NXKR5c2R0=; b=UM9L0qJ8x4mkRYyQ0OEA2ZU2AIfQ+vwgYFIyktB1YYlGYtr2Zagye9BH pPMqCt6rQhmzzKqGEOqKwkcwpqMw8BOvB3gpztzgr8M9FNNkoMQr1wM5W EFeoOKvbjyLhTNKcHpkSfckomTQAtXEvV7ud/RmuzGpCX35z+2C1HNJUJ hIjr4msCv19WRkd/QQySEwC1rNmh6J9sdigaBsYHvZR9mO02JkrDlSf/S ZWWF1m5xCx+oCEGvzJe42U/jwYueMQpjOpmIUaheEBVXAwEe1bYisM+Jf pMzqdV+TDaOHTGLp1B9KauzFT+w8VDE1iHtxLWNfnHScVuUM3Qk7PHjER g==; X-CSE-ConnectionGUID: z96k+3+HSwOsQKUbL3ZicQ== X-CSE-MsgGUID: OrTpFGyvQ6iTgu00DeVLIA== X-IronPort-AV: E=McAfee;i="6800,10657,11902"; a="88572484" X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="88572484" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Sep 2026 14:40:42 -0700 X-CSE-ConnectionGUID: 93hrEfdsTqmTNdCVcTCXAA== X-CSE-MsgGUID: wD5yX24cRgeYyN93LVyqrA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="272004001" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa007.jf.intel.com with ESMTP; 11 Sep 2026 14:40:41 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Paolo Bonzini , Sean Christopherson , Jonathan Corbet , Shuah Khan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Xin Li , Andy Lutomirski , Peter Zijlstra , Andrew Cooper , Tom Lendacky , Nikunj A Dadhania , Shivansh Dhiman , David Woodhouse , Chao Gao , Binbin Wu , Sohil Mehta , Zhao Liu , Yosry Ahmed , David Matlack , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v10 06/28] x86/fred: Export this_cpu_fred_rsp() for KVM usage Date: Fri, 11 Sep 2026 14:36:36 -0700 Message-ID: <20260911213659.2025974-7-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260911213659.2025974-1-sohil.mehta@intel.com> References: <20260911213659.2025974-1-sohil.mehta@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: "Xin Li (Intel)" Introduce and export this_cpu_fred_rsp() to provide KVM with a self- explanatory interface for retrieving per-CPU FRED regular stacks for stack levels 1->3. FRED introduced new fields in the VMCS host-state area for stack levels 1=E2=80=93>3 (HOST_IA32_FRED_RSP[123]), which correspond to the per-CPU FRED regular stacks for stack levels 1->3. KVM must populate these fields each time a vCPU is loaded onto a CPU to ensure a complete valid FRED event delivery context immediately after any VM-Exits. Signed-off-by: Xin Li (Intel) Signed-off-by: Sohil Mehta --- v10: - Replace direct, raw use of __this_cpu_ist_top_va() with a self- explanatory this_cpu_fred_rsp() helper for better readability (Sean). --- arch/x86/include/asm/fred.h | 10 ++++++++++ arch/x86/kernel/fred.c | 24 +++++++++++++++++++++--- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/fred.h b/arch/x86/include/asm/fred.h index 18a2f811c358..85b851f16bae 100644 --- a/arch/x86/include/asm/fred.h +++ b/arch/x86/include/asm/fred.h @@ -35,6 +35,13 @@ =20 #ifndef __ASSEMBLER__ =20 +enum fred_stack_level { + FRED_STACK_LEVEL_0, + FRED_STACK_LEVEL_1, + FRED_STACK_LEVEL_2, + FRED_STACK_LEVEL_3 +}; + #ifdef CONFIG_X86_FRED #include #include @@ -105,6 +112,8 @@ static __always_inline void fred_update_rsp0(void) __this_cpu_write(fred_rsp0, rsp0); } } + +unsigned long this_cpu_fred_rsp(enum fred_stack_level lvl); #else /* CONFIG_X86_FRED */ static __always_inline unsigned long fred_event_data(struct pt_regs *regs)= { return 0; } static inline void cpu_init_fred_exceptions(void) { } @@ -112,6 +121,7 @@ static inline void cpu_init_fred_rsps(void) { } static inline void fred_complete_exception_setup(void) { } static inline void fred_sync_rsp0(unsigned long rsp0) { } static inline void fred_update_rsp0(void) { } +static inline unsigned long this_cpu_fred_rsp(enum fred_stack_level lvl) {= return 0; } #endif /* CONFIG_X86_FRED */ #endif /* !__ASSEMBLER__ */ =20 diff --git a/arch/x86/kernel/fred.c b/arch/x86/kernel/fred.c index 1c452a389a70..68947c53a494 100644 --- a/arch/x86/kernel/fred.c +++ b/arch/x86/kernel/fred.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ #include +#include =20 #include #include @@ -69,6 +70,23 @@ void cpu_init_fred_exceptions(void) setup_clear_cpu_cap(X86_FEATURE_SYSCALL32); } =20 +unsigned long this_cpu_fred_rsp(enum fred_stack_level lvl) +{ + switch (lvl) { + case FRED_STACK_LEVEL_0: + return __this_cpu_read(fred_rsp0); + case FRED_STACK_LEVEL_1: + return __this_cpu_ist_top_va(ESTACK_DB); + case FRED_STACK_LEVEL_2: + return __this_cpu_ist_top_va(ESTACK_NMI); + case FRED_STACK_LEVEL_3: + return __this_cpu_ist_top_va(ESTACK_DF); + default: + BUG(); + } +} +EXPORT_SYMBOL_FOR_KVM(this_cpu_fred_rsp); + /* Must be called after setup_cpu_entry_areas() */ void cpu_init_fred_rsps(void) { @@ -84,7 +102,7 @@ void cpu_init_fred_rsps(void) FRED_STKLVL(X86_TRAP_DF, FRED_DF_STACK_LEVEL)); =20 /* The FRED equivalents to IST stacks... */ - wrmsrq(MSR_IA32_FRED_RSP1, __this_cpu_ist_top_va(ESTACK_DB)); - wrmsrq(MSR_IA32_FRED_RSP2, __this_cpu_ist_top_va(ESTACK_NMI)); - wrmsrq(MSR_IA32_FRED_RSP3, __this_cpu_ist_top_va(ESTACK_DF)); + wrmsrq(MSR_IA32_FRED_RSP1, this_cpu_fred_rsp(FRED_STACK_LEVEL_1)); + wrmsrq(MSR_IA32_FRED_RSP2, this_cpu_fred_rsp(FRED_STACK_LEVEL_2)); + wrmsrq(MSR_IA32_FRED_RSP3, this_cpu_fred_rsp(FRED_STACK_LEVEL_3)); } --=20 2.43.0 From nobody Fri Sep 25 13:16:55 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) (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 B29404A4984; Fri, 11 Sep 2026 21:40:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162855; cv=none; b=byweZD9DRk64ZTbYBkmDa3WkpnOIAVV8qSG9i6F2l07U2FPx4O0Ob4LRrJxfqybvkc2MwNorwC4xBeASgXg3GYLASw/zR6yG5PJSzjsENpiMvCJpYZliWw0FA7ahJOkReHL9kG+Hpfd0fk7V6OKU4X7pG7E30AxyKfgW4jNs974= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162855; c=relaxed/simple; bh=OHMvTxwx8WmR6ep9J+RcwSCq9HXroTytnAPdrb0CwxQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MepujKYpWKYFRKZO8Cz+lqHgvE16/pWuKKO9iysKg6WVI4OqByR5qqkZ6RXKc24oAPjoRUFqym+Lw1WiYT8XeZRSwwFVdfqpUctkvP9Y9lUbbA+HuriH8+ATYMzd5QhYeaKMfGbRIVqTRGj7DokOOMMWww4cTIMLg0j6dsVjSZ8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=UIsZfn0p; arc=none smtp.client-ip=192.198.163.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="UIsZfn0p" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789162853; x=1820698853; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=OHMvTxwx8WmR6ep9J+RcwSCq9HXroTytnAPdrb0CwxQ=; b=UIsZfn0pcUJC8hTk+GVxybkdVVRvjgbz/A3Jl2cL7SHywjDOwgnsGs7v t993GrT2yj5oi3SITv3lDqKImT+tkmP8n5T3JRu5sGastGd0HcMOr8oDU p6TdqYLMqX6z6LQQdqL1abqYN4VeB0b87DetFDdI+s8mxDn48ZVnMLMsF p3ooMIVPnMXV++CSfwV+q65y1W/sU9kLWRBG/LvDiZwDhr2XTqeLxVwcj Xv+XkMJZEBWKjQo4WDVjg8OkOp69+5PpblGxYh4Jtjv0GQL83j6AWTs+p 4ZSbqlf/KEWwmGMvsWlBJIncrT4jqiHgJzNu2ryEW4clxIx8zPq6x+IOL A==; X-CSE-ConnectionGUID: eentJmiLTZGnHjBUdN99vg== X-CSE-MsgGUID: cbqcUK3jQg+TlaCuK/Vzfg== X-IronPort-AV: E=McAfee;i="6800,10657,11902"; a="88572502" X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="88572502" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Sep 2026 14:40:52 -0700 X-CSE-ConnectionGUID: CvQRHx7pQQOiI64O8Vt9mA== X-CSE-MsgGUID: je4Zy9atSymj2NENkdBA/A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="272004040" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa007.jf.intel.com with ESMTP; 11 Sep 2026 14:40:51 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Paolo Bonzini , Sean Christopherson , Jonathan Corbet , Shuah Khan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Xin Li , Andy Lutomirski , Peter Zijlstra , Andrew Cooper , Tom Lendacky , Nikunj A Dadhania , Shivansh Dhiman , David Woodhouse , Chao Gao , Binbin Wu , Sohil Mehta , Zhao Liu , Yosry Ahmed , David Matlack , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v10 07/28] KVM: VMX: Initialize VMCS FRED fields Date: Fri, 11 Sep 2026 14:36:37 -0700 Message-ID: <20260911213659.2025974-8-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260911213659.2025974-1-sohil.mehta@intel.com> References: <20260911213659.2025974-1-sohil.mehta@intel.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 (Intel)" 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 (Intel) Signed-off-by: Sohil Mehta Reviewed-by: Chao Gao Reviewed-by: Binbin Wu --- v10: - s/rdmsrl/rdmsrq (Chao) - Remove a terse comment which doesn't help at all (Sean). - Replace direct, raw use of __this_cpu_ist_top_va() with a self- explanatory this_cpu_fred_rsp() helper for better readability (Sean). - Add cpu_feature_enabled(X86_FEATURE_FRED) to patch out accesses to VMCS FRED fields (Sean). - Remove "#ifdef CONFIG_X86_64" after switching to this_cpu_fred_rsp() (Sean). --- arch/x86/include/asm/kvm_host.h | 3 +++ arch/x86/include/asm/vmx.h | 32 ++++++++++++++++++++++++++++++++ arch/x86/kvm/vmx/vmx.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index 683bb8bf43a9..8d3999772ac2 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -294,6 +294,9 @@ struct kvm_host_values { u64 xss; u64 s_cet; u64 arch_capabilities; + + u64 fred_config; + u64 fred_stklvls; }; extern struct kvm_host_values kvm_host; =20 diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h index 682f09933612..4720619f09ac 100644 --- a/arch/x86/include/asm/vmx.h +++ b/arch/x86/include/asm/vmx.h @@ -306,12 +306,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 2a2218e0983b..dc80ca5f804d 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -1562,6 +1562,12 @@ void vmx_vcpu_load_vmcs(struct kvm_vcpu *vcpu, int c= pu) (unsigned long)(cpu_entry_stack(cpu) + 1)); } =20 + if (cpu_feature_enabled(X86_FEATURE_FRED) && kvm_cpu_cap_has(X86_FEATURE= _FRED)) { + vmcs_write64(HOST_IA32_FRED_RSP1, this_cpu_fred_rsp(FRED_STACK_LEVEL_1)= ); + vmcs_write64(HOST_IA32_FRED_RSP2, this_cpu_fred_rsp(FRED_STACK_LEVEL_2)= ); + vmcs_write64(HOST_IA32_FRED_RSP3, this_cpu_fred_rsp(FRED_STACK_LEVEL_3)= ); + } + vmx->loaded_vmcs->cpu =3D cpu; } } @@ -4500,6 +4506,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 (cpu_feature_enabled(X86_FEATURE_FRED) && 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 */ @@ -5030,6 +5047,17 @@ static void init_vmcs(struct vcpu_vmx *vmx) } =20 vmx_setup_uret_msrs(vmx); + + if (cpu_feature_enabled(X86_FEATURE_FRED) && 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) @@ -8883,6 +8911,11 @@ __init int vmx_hardware_setup(void) =20 kvm_caps.inapplicable_quirks &=3D ~KVM_X86_QUIRK_IGNORE_GUEST_PAT; =20 + if (cpu_feature_enabled(X86_FEATURE_FRED) && kvm_cpu_cap_has(X86_FEATURE_= FRED)) { + rdmsrq(MSR_IA32_FRED_CONFIG, kvm_host.fred_config); + rdmsrq(MSR_IA32_FRED_STKLVLS, kvm_host.fred_stklvls); + } + return 0; } =20 --=20 2.43.0 From nobody Fri Sep 25 13:16:55 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) (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 A820A4570D1; Fri, 11 Sep 2026 21:40:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162861; cv=none; b=F6768CZNp1k8X6dm6eljMIzOMgQiHMviskUKeCkDx46BStdn2RrYLbuWK4itFzPsDgi4vGoA7MhqgyOD/3d9WAq/4drRYRGQh8U9NXjM3vY6rKtbayu4zE7vTXP5nPgO8uVXSlZjWp+JL16MOxJ24cgmC2oivpBuFvq+tLMVdP8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162861; c=relaxed/simple; bh=0qNqsEIyAeCzzxembfEaW2mKNJ3cFGzdVIOVID9El58=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=kNklHi4UaAhOIm0ZE+6diklH4QjbsOmZiY/F+7fO4zBE7dyTKmgfHOzFWeP/MqL1hQbObozLUoyQopRrEqW+ioZlrAMfkvYrgLroFNyeL2QqMpDsnGGb4SKeTpyFzu/0dYKR7fod6mBDZRLkDlLZ9oVveO6ipFNEaeHsg0AqWlQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=kZ/o2cdh; arc=none smtp.client-ip=192.198.163.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="kZ/o2cdh" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789162860; x=1820698860; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=0qNqsEIyAeCzzxembfEaW2mKNJ3cFGzdVIOVID9El58=; b=kZ/o2cdhQxkHcbDuNrnUAvs4Vn4KrTMJ7sXJaDLzyivPlOB9xhrRtL8V ws9150JdfKZCI1a5SbAN5l/+sjvB/jCOm2TogpXULRMnN18YELEnrc87f E8LTthh06ci/mFFm7CL795bBn87izfFjEQBSYvl+1+bzl9c0iEIJy32eE Wi/mkmAtiYmgAozXl8KKNBTdVDsqAYLTEb47OnX+F3AedGMFwqE+jaoFA CkHAdvOnTBaXyJHmuZnwwkSeT3C1bvLqrG3r7uHT9F2H50rKBbLgPctw5 Ycytcj+NDUwmLb/2AOpeVrA1zOkHChDfEUjLcR+lvrAW0lZhz7Prpv9NV Q==; X-CSE-ConnectionGUID: R5k87XRkTZa1uIpx7VfmOg== X-CSE-MsgGUID: r0lTKtFORIS2fqpJQwmokg== X-IronPort-AV: E=McAfee;i="6800,10657,11902"; a="88572525" X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="88572525" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Sep 2026 14:40:59 -0700 X-CSE-ConnectionGUID: 72scEmk5SxeR29gVwOMcew== X-CSE-MsgGUID: jkbnjOJjQ0GfAT3RPsq5hQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="272004049" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa007.jf.intel.com with ESMTP; 11 Sep 2026 14:40:58 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Paolo Bonzini , Sean Christopherson , Jonathan Corbet , Shuah Khan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Xin Li , Andy Lutomirski , Peter Zijlstra , Andrew Cooper , Tom Lendacky , Nikunj A Dadhania , Shivansh Dhiman , David Woodhouse , Chao Gao , Binbin Wu , Sohil Mehta , Zhao Liu , Yosry Ahmed , David Matlack , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v10 08/28] KVM: VMX: Set FRED MSR intercepts Date: Fri, 11 Sep 2026 14:36:38 -0700 Message-ID: <20260911213659.2025974-9-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260911213659.2025974-1-sohil.mehta@intel.com> References: <20260911213659.2025974-1-sohil.mehta@intel.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 (Intel)" On a userspace MSR filter change, set FRED MSR intercepts. Because the following eight FRED MSRs, MSR_IA32_FRED_RSP[123], MSR_IA32_FRED_STKLVLS, MSR_IA32_FRED_SSP[123], MSR_IA32_FRED_CONFIG, are used by the kernel itself to take an exception at any time, they should be context-switched by Intel VT-x automatically in order to preserve the FRED architectural invariant that there should NEVER be a "gap" during which it is unsafe to take an exception. KVM leverages Intel VT-x hardware to automatically context switch the eight FRED MSRs using: 1) Dedicated host and guest VMCS fields for each MSR. 2) VM-entry/exit controls to manage the automated loading and saving of the eight FRED MSRs. Consequently, passing these MSRs through to the guest would only add unnecessary handling code without benefit. Both MSR_IA32_FRED_RSP0 and MSR_IA32_FRED_SSP0 (aka MSR_IA32_PL0_SSP) are dedicated for userspace event delivery, IOW they are NOT used in any kernel event delivery and the execution of ERETS. Thus KVM can run safely with guest values in the two MSRs. As a result, save and restore of their guest values are deferred until vCPU context switch, Host MSR_IA32_FRED_RSP0 is restored upon returning to userspace, and Host MSR_IA32_PL0_SSP is managed with XRSTORS/XSAVES. MSR_IA32_PL0_SSP (aka MSR_IA32_FRED_SSP0) is part of CET supervisor state, but all four FRED SSP MSRs are architecturally visible on any processor that enumerates FRED. Even if CET is absent, these MSRs remain accessible via RDMSR/WRMSR, though FRED transitions will not use them. Intercept MSR_IA32_PL0_SSP if CET shadow stacks are unsupported (even with FRED present). Since this MSR is rarely accessed and ignored by XSAVES in this configuration, interception avoids the overhead of manually context switching the hardware MSR during vcpu_load/put. This behavior is consistent with the current setup in vmx_recalc_msr_intercepts(), so no change is needed to the interception logic for MSR_IA32_PL0_SSP. Signed-off-by: Xin Li (Intel) Signed-off-by: Sohil Mehta --- v10: - Improve the commit message and code comment with an explanation from hpa (Chao Gao and Dave Hansen). --- arch/x86/kvm/vmx/vmx.c | 67 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index dc80ca5f804d..09bbbc680aa7 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -4304,6 +4304,72 @@ static void vmx_recalc_pmu_msr_intercepts(struct kvm= _vcpu *vcpu) MSR_TYPE_RW, intercept); } =20 +static void vmx_set_intercept_for_fred_msr(struct kvm_vcpu *vcpu) +{ + bool intercept =3D !guest_cpu_cap_has(vcpu, X86_FEATURE_FRED); + + if (!kvm_cpu_cap_has(X86_FEATURE_FRED)) + return; + + /* + * Because the following eight FRED MSRs, + * MSR_IA32_FRED_RSP[123], MSR_IA32_FRED_STKLVLS, + * MSR_IA32_FRED_SSP[123], MSR_IA32_FRED_CONFIG, + * are used by the kernel itself to take an exception at any time, they + * should be context-switched by Intel VT-x automatically in order to + * preserve the FRED architectural invariant that there should NEVER be + * a "gap" during which it is unsafe to take an exception. + * + * KVM leverages Intel VT-x hardware to automatically context switch the + * eight FRED MSRs using: + * + * 1) Dedicated host and guest VMCS fields for each MSR. + * + * 2) VM-entry/exit controls to manage the automated loading and saving + * of the eight FRED MSRs. + * + * Consequently, passing these MSRs through to the guest would only add + * unnecessary handling code without benefit. + */ + vmx_set_intercept_for_msr(vcpu, MSR_IA32_FRED_RSP1, MSR_TYPE_RW, intercep= t); + vmx_set_intercept_for_msr(vcpu, MSR_IA32_FRED_RSP2, MSR_TYPE_RW, intercep= t); + vmx_set_intercept_for_msr(vcpu, MSR_IA32_FRED_RSP3, MSR_TYPE_RW, intercep= t); + vmx_set_intercept_for_msr(vcpu, MSR_IA32_FRED_STKLVLS, MSR_TYPE_RW, inter= cept); + vmx_set_intercept_for_msr(vcpu, MSR_IA32_FRED_SSP1, MSR_TYPE_RW, intercep= t); + vmx_set_intercept_for_msr(vcpu, MSR_IA32_FRED_SSP2, MSR_TYPE_RW, intercep= t); + vmx_set_intercept_for_msr(vcpu, MSR_IA32_FRED_SSP3, MSR_TYPE_RW, intercep= t); + vmx_set_intercept_for_msr(vcpu, MSR_IA32_FRED_CONFIG, MSR_TYPE_RW, interc= ept); + + /* + * MSR_IA32_FRED_RSP0 and MSR_IA32_PL0_SSP (aka MSR_IA32_FRED_SSP0) are + * designed for event delivery while executing in userspace. Since KVM + * operates entirely in kernel mode (CPL is always 0 after any VM exit), + * it can safely retain and operate with guest-defined values for these + * MSRs. + * + * Disabling interception of the two MSRs offers two advantages: + * 1) Simplicity: Eliminates dedicated MSR handling code. + * 2) Performance: Avoids frequent VM-exits since the two MSRs are + * per user thread variables and frequently accessed. + * + * MSR_IA32_PL0_SSP (aka MSR_IA32_FRED_SSP0) is part of CET supervisor + * state, but all four FRED SSP MSRs are architecturally visible on any + * processor that enumerates FRED. Even if CET is absent, these MSRs + * remain accessible via RDMSR/WRMSR, though FRED transitions will not + * use them. + * + * Intercept MSR_IA32_PL0_SSP if CET shadow stacks are unsupported (even + * with FRED present). Since this MSR is rarely accessed and ignored by + * XSAVES in this configuration, interception avoids the overhead of + * manually context switching the hardware MSR during vcpu_load/put. + * + * This behavior is consistent with the current setup in + * vmx_recalc_msr_intercepts(), so no change is needed to the interception + * logic for MSR_IA32_PL0_SSP. + */ + vmx_set_intercept_for_msr(vcpu, MSR_IA32_FRED_RSP0, MSR_TYPE_RW, intercep= t); +} + static void vmx_recalc_msr_intercepts(struct kvm_vcpu *vcpu) { bool intercept; @@ -4371,6 +4437,7 @@ static void vmx_recalc_msr_intercepts(struct kvm_vcpu= *vcpu) } =20 vmx_recalc_pmu_msr_intercepts(vcpu); + vmx_set_intercept_for_fred_msr(vcpu); =20 /* * x2APIC and LBR MSR intercepts are modified on-demand and cannot be --=20 2.43.0 From nobody Fri Sep 25 13:16:55 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) (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 707E948663E; Fri, 11 Sep 2026 21:41:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162872; cv=none; b=BmjpVUUcm4CwwbQvRSFDaTmipdV5iZZh9/S5K5X2E9tDzBOlj2k7YJyGyoJ4hyH7Kw+w36eNtOsE/WKgDp73P6aSBY2HrgoVCpfcrr8Yb053jn4j8aaJlanTCJJf2f8k8TRXIt9EoUEnjISKo0JvJAJFxE6PNLO36mE83ng/x7w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162872; c=relaxed/simple; bh=oGW+uzEXEc0mTanrOErJYE0T2Ofyhqc9C3G0tII9PdY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CFprIxEGzgoEA5g3pjUmg5HVJqhpgNUnTuvhjrhBsVoD3M1Fc/IRl2I06i8xLE2EyyLccpDcyRTDdWIV3oHjTBZJc2QFGK/h6kusALu3rY5OSPfEqw7+cKfQZmyHZSGIu2Q3Fn+RAXgCyg+IQw4ZtVaikhO/UlZ+L8gK6EPxMQM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=Ii9HB16t; arc=none smtp.client-ip=192.198.163.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="Ii9HB16t" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789162871; x=1820698871; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=oGW+uzEXEc0mTanrOErJYE0T2Ofyhqc9C3G0tII9PdY=; b=Ii9HB16tweFcRu+vzC9pMPbBXSiKx5F7yDpXZOL2aq38z137gA704S0h FCGlBfUEw5Bl+I6HNZZPOyFgO64NiLMIXFT4e+UCoVO2YjnrHHiuDRXbb TM+DDrrqjf06fvaNOnoAsbbIZYNU52S4b/hV+vS5oDrD1fbLMR11IgCyn ZlRrQsdKwqYqRC/BOtfQ2RItFQf8jQtSb9WUxBwbcGZRbx9+XpWeuPmIE o2WgF4PqzhUlwAQkeu9LWtAeGISF1O2/yYy0oBNLnYBjJdm+a98L6zuM0 /CliSUtFHEGXLxMGNsBHJv7504LL98BmD3G2OHOBV61lPKNxc8cTADbv8 w==; X-CSE-ConnectionGUID: myEI+jnjQwm6Bsbkho3GAg== X-CSE-MsgGUID: sKmmNtU7TeyF8AW7aYz3JA== X-IronPort-AV: E=McAfee;i="6800,10657,11902"; a="88572547" X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="88572547" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Sep 2026 14:41:10 -0700 X-CSE-ConnectionGUID: yeFQZaU5RrGPsnTdg6YT7g== X-CSE-MsgGUID: lfK9+TYaR8SLgEFjtP55QA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="272004062" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa007.jf.intel.com with ESMTP; 11 Sep 2026 14:41:09 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Paolo Bonzini , Sean Christopherson , Jonathan Corbet , Shuah Khan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Xin Li , Andy Lutomirski , Peter Zijlstra , Andrew Cooper , Tom Lendacky , Nikunj A Dadhania , Shivansh Dhiman , David Woodhouse , Chao Gao , Binbin Wu , Sohil Mehta , Zhao Liu , Yosry Ahmed , David Matlack , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v10 09/28] KVM: VMX: Save/restore guest FRED RSP0 Date: Fri, 11 Sep 2026 14:36:39 -0700 Message-ID: <20260911213659.2025974-10-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260911213659.2025974-1-sohil.mehta@intel.com> References: <20260911213659.2025974-1-sohil.mehta@intel.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 (Intel)" Save guest FRED RSP0 in vmx_prepare_switch_to_host() and restore it in vmx_prepare_switch_to_guest() because MSR_IA32_FRED_RSP0 is passed through to the guest, thus is volatile/unknown. Note, host FRED RSP0 is restored in arch_exit_to_user_mode_prepare(), regardless of whether it is modified in KVM. Signed-off-by: Xin Li (Intel) Signed-off-by: Sohil Mehta Reviewed-by: Chao Gao Reviewed-by: Binbin Wu --- v10: - No change Note, an equivalent TDX side implementation is missing. No TDX module with FRED support exists yet so this would be an issue for future platforms. A generic discussion regarding this is ongoing at: https://lore.kernel.org/kvm/20260827031837.2863609-1-binbin.wu@linux.intel.= com/ --- arch/x86/kvm/vmx/vmx.c | 13 +++++++++++++ arch/x86/kvm/vmx/vmx.h | 1 + 2 files changed, 14 insertions(+) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 09bbbc680aa7..b6b73ab9cfb7 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -1395,6 +1395,9 @@ void vmx_prepare_switch_to_guest(struct kvm_vcpu *vcp= u) } =20 wrmsrq(MSR_KERNEL_GS_BASE, vmx->msr_guest_kernel_gs_base); + + if (guest_cpu_cap_has(vcpu, X86_FEATURE_FRED)) + wrmsrns(MSR_IA32_FRED_RSP0, vmx->msr_guest_fred_rsp0); #else savesegment(fs, fs_sel); savesegment(gs, gs_sel); @@ -1439,6 +1442,16 @@ static void vmx_prepare_switch_to_host(struct vcpu_v= mx *vmx) invalidate_tss_limit(); #ifdef CONFIG_X86_64 wrmsrq(MSR_KERNEL_GS_BASE, vmx->vt.msr_host_kernel_gs_base); + + if (guest_cpu_cap_has(&vmx->vcpu, X86_FEATURE_FRED)) { + vmx->msr_guest_fred_rsp0 =3D read_msr(MSR_IA32_FRED_RSP0); + /* + * Synchronize the current value in hardware to the kernel's + * local cache. The desired host RSP0 will be set when the + * CPU exits to userspace (RSP0 is a per-task value). + */ + fred_sync_rsp0(vmx->msr_guest_fred_rsp0); + } #endif load_fixmap_gdt(raw_smp_processor_id()); vmx->vt.guest_state_loaded =3D false; diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index 7a22e1b1a273..14fd3f57d5c1 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -222,6 +222,7 @@ struct vcpu_vmx { bool guest_uret_msrs_loaded; #ifdef CONFIG_X86_64 u64 msr_guest_kernel_gs_base; + u64 msr_guest_fred_rsp0; #endif =20 u64 spec_ctrl; --=20 2.43.0 From nobody Fri Sep 25 13:16:55 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) (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 EB01F48663E; Fri, 11 Sep 2026 21:41:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162882; cv=none; b=eXW7oHrTMNOR8pVok+CA0uETFwvECYpraJy2b8H6IcsxutH+eED1yXrsLpxVc7VFiwAThkE7m/wxcFJycTYxGN1erw7lBRhAux4RvOLSAhwYhuffqHBukiBXsiGf7OHFtjwUW2RhINaYxnJF/R/n1n5WxjD/M65hEjw4Q+HKW68= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162882; c=relaxed/simple; bh=pTC5a4/Yt0WjHvZekgLXWfLwG+w0fYiORfetO1Na3Oc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=R9Gx6e/zTBo3MobYyJHPu+PGvoL1QoIIqIb/dJMWEn1OMTjbulR1DtzxAGH96GKAhm9V8A7H+eg9rnKlFo8zhG16ZCKYtMcK7cAcXVZQUuWs978O9FCw4hLXC1bkZu+TOlAkfG0gDdmFdjWkDbCqoB+jFLSDVErUi+SJf5wijaQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=dmTG69U7; arc=none smtp.client-ip=192.198.163.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="dmTG69U7" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789162881; x=1820698881; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=pTC5a4/Yt0WjHvZekgLXWfLwG+w0fYiORfetO1Na3Oc=; b=dmTG69U7ciwgw1Zdx0O1asBlFFy+g2P+KkmPcjPsn5IfhVkZi2jgQyNA yuPS3Sa1umDu7x3fC9EYkeP6clY8DVeCZSFXeBzYR9JR/IlJvOqePkgiG rXZumeTQPhJq5edE3Z41wZdAv+sePupZIDl8XCbvYOQJ/qWHd+M7UrJZB 8PJg/gjx+k7FbEW+1N4yLbZbhLygtGRzUMV7GVm/ckT8WpS10//bPNhBF M+2HY/4SsrN9OLD7Fpnl/qlaRZPSvwJjHt2L9TwNJ4YkWZ+t6JCKUvRfR HPsYjt7VFOxu8s+RN9cmQZPvdjgamVGZ7H8N2eAo9Ulp58XB3J0FQt8x0 Q==; X-CSE-ConnectionGUID: BBVoSd2USAS+grbwj+yUeA== X-CSE-MsgGUID: BbCXnO6aR02LPyuUAXqUyg== X-IronPort-AV: E=McAfee;i="6800,10657,11902"; a="88572584" X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="88572584" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Sep 2026 14:41:20 -0700 X-CSE-ConnectionGUID: B5O9CTF/RA2tVLer98aADw== X-CSE-MsgGUID: l6CDTyODSA6U1zmDENhvvg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="272004074" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa007.jf.intel.com with ESMTP; 11 Sep 2026 14:41:19 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Paolo Bonzini , Sean Christopherson , Jonathan Corbet , Shuah Khan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Xin Li , Andy Lutomirski , Peter Zijlstra , Andrew Cooper , Tom Lendacky , Nikunj A Dadhania , Shivansh Dhiman , David Woodhouse , Chao Gao , Binbin Wu , Sohil Mehta , Zhao Liu , Yosry Ahmed , David Matlack , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v10 10/28] KVM: VMX: Add support for saving and restoring FRED MSRs Date: Fri, 11 Sep 2026 14:36:40 -0700 Message-ID: <20260911213659.2025974-11-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260911213659.2025974-1-sohil.mehta@intel.com> References: <20260911213659.2025974-1-sohil.mehta@intel.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 (Intel)" Introduce support for handling FRED MSR access requests, enabling both host and guest to read and write FRED MSRs, which is essential for VM save/restore and live migration, and allows userspace tools such as QEMU to access the relevant MSRs. Specially, intercept accesses to the FRED SSP0 MSR (IA32_PL0_SSP), which remains accessible when FRED is enumerated even if CET is not. This ensures the guest value is fully virtual and does not alter the hardware FRED SSP0 MSR. Signed-off-by: Xin Li (Intel) Signed-off-by: Sohil Mehta Reviewed-by: Chao Gao --- v10: - Fix a corner case identified by Chao Gao. --- arch/x86/include/asm/kvm_host.h | 5 ++ arch/x86/include/asm/msr-index.h | 2 + arch/x86/kvm/msrs.c | 89 ++++++++++++++++++++++++++++++-- arch/x86/kvm/vmx/vmx.c | 45 ++++++++++++++++ 4 files changed, 138 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index 8d3999772ac2..0fd5d4edeebb 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1032,6 +1032,11 @@ struct kvm_vcpu_arch { #if IS_ENABLED(CONFIG_HYPERV) hpa_t hv_root_tdp; #endif + /* + * Stores the FRED SSP0 MSR when CET is not supported, prompting KVM + * to intercept its accesses. + */ + u64 fred_ssp0_fallback; }; =20 struct kvm_lpage_info { diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-in= dex.h index ad899d9070e1..b386709515c4 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -64,6 +64,8 @@ #define MSR_IA32_FRED_SSP3 0x1d3 /* Level 3 shadow stack pointer */ #define MSR_IA32_FRED_CONFIG 0x1d4 /* Entrypoint and interrupt stack lev= el */ =20 +#define FRED_CONFIG_RESERVED (BIT_ULL(2) | GENMASK_ULL(5, 4) | BIT_ULL(11)) + /* Intel MSRs. Some also available on other CPUs */ #define MSR_TEST_CTRL 0x00000033 #define MSR_TEST_CTRL_SPLIT_LOCK_DETECT_BIT 29 diff --git a/arch/x86/kvm/msrs.c b/arch/x86/kvm/msrs.c index 66fa7140d65d..9eabb7b02cb5 100644 --- a/arch/x86/kvm/msrs.c +++ b/arch/x86/kvm/msrs.c @@ -193,6 +193,9 @@ static const u32 msrs_to_save_base[] =3D { MSR_STAR, #ifdef CONFIG_X86_64 MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR, + MSR_IA32_FRED_RSP0, MSR_IA32_FRED_RSP1, MSR_IA32_FRED_RSP2, + MSR_IA32_FRED_RSP3, MSR_IA32_FRED_STKLVLS, MSR_IA32_FRED_SSP1, + MSR_IA32_FRED_SSP2, MSR_IA32_FRED_SSP3, MSR_IA32_FRED_CONFIG, #endif MSR_IA32_TSC, MSR_IA32_CR_PAT, MSR_VM_HSAVE_PA, MSR_IA32_FEAT_CTL, MSR_IA32_BNDCFGS, MSR_TSC_AUX, @@ -772,7 +775,7 @@ static int __kvm_set_msr(struct kvm_vcpu *vcpu, u32 ind= ex, u64 data, * architecture. Intercepting XRSTORS/XSAVES for this * special case isn't deemed worthwhile. */ - case MSR_IA32_PL0_SSP ... MSR_IA32_INT_SSP_TAB: + case MSR_IA32_PL1_SSP ... MSR_IA32_INT_SSP_TAB: if (!guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK)) return KVM_MSR_RET_UNSUPPORTED; /* @@ -787,6 +790,52 @@ static int __kvm_set_msr(struct kvm_vcpu *vcpu, u32 in= dex, u64 data, if (index !=3D MSR_IA32_INT_SSP_TAB && !IS_ALIGNED(data, 4)) return 1; break; + case MSR_IA32_FRED_STKLVLS: + if (!guest_cpu_cap_has(vcpu, X86_FEATURE_FRED)) + return KVM_MSR_RET_UNSUPPORTED; + break; + case MSR_IA32_FRED_RSP0 ... MSR_IA32_FRED_RSP3: + case MSR_IA32_FRED_SSP1 ... MSR_IA32_FRED_CONFIG: { + u64 reserved_bits =3D 0; + + if (!guest_cpu_cap_has(vcpu, X86_FEATURE_FRED)) + return KVM_MSR_RET_UNSUPPORTED; + + if (is_noncanonical_msr_address(data, vcpu)) + return 1; + + switch (index) { + case MSR_IA32_FRED_CONFIG: + reserved_bits =3D FRED_CONFIG_RESERVED; + break; + case MSR_IA32_FRED_RSP0 ... MSR_IA32_FRED_RSP3: + reserved_bits =3D GENMASK_ULL(5, 0); + break; + case MSR_IA32_FRED_SSP1 ... MSR_IA32_FRED_SSP3: + reserved_bits =3D GENMASK_ULL(2, 0); + break; + default: + WARN_ON_ONCE(1); + return 1; + } + + if (data & reserved_bits) + return 1; + + break; + } + case MSR_IA32_PL0_SSP: /* I.e., MSR_IA32_FRED_SSP0 */ + if (!guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK) && + !guest_cpu_cap_has(vcpu, X86_FEATURE_FRED)) + return KVM_MSR_RET_UNSUPPORTED; + + if (is_noncanonical_msr_address(data, vcpu)) + return 1; + + if (!IS_ALIGNED(data, 4)) + return 1; + + break; } =20 msr.data =3D data; @@ -841,10 +890,19 @@ static int __kvm_get_msr(struct kvm_vcpu *vcpu, u32 i= ndex, u64 *data, if (!host_initiated) return 1; fallthrough; - case MSR_IA32_PL0_SSP ... MSR_IA32_INT_SSP_TAB: + case MSR_IA32_PL1_SSP ... MSR_IA32_INT_SSP_TAB: if (!guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK)) return KVM_MSR_RET_UNSUPPORTED; break; + case MSR_IA32_FRED_RSP0 ... MSR_IA32_FRED_CONFIG: + if (!guest_cpu_cap_has(vcpu, X86_FEATURE_FRED)) + return KVM_MSR_RET_UNSUPPORTED; + break; + case MSR_IA32_PL0_SSP: /* I.e., MSR_IA32_FRED_SSP0 */ + if (!guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK) && + !guest_cpu_cap_has(vcpu, X86_FEATURE_FRED)) + return KVM_MSR_RET_UNSUPPORTED; + break; } =20 msr.index =3D index; @@ -1833,7 +1891,15 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct= msr_data *msr_info) break; #endif case MSR_IA32_U_CET: + kvm_set_xstate_msr(vcpu, msr_info); + break; case MSR_IA32_PL0_SSP ... MSR_IA32_PL3_SSP: + if (!guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK)) { + WARN_ON_ONCE(msr !=3D MSR_IA32_FRED_SSP0); + vcpu->arch.fred_ssp0_fallback =3D data; + break; + } + kvm_set_xstate_msr(vcpu, msr_info); break; default: @@ -2186,7 +2252,15 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct= msr_data *msr_info) break; #endif case MSR_IA32_U_CET: + kvm_get_xstate_msr(vcpu, msr_info); + break; case MSR_IA32_PL0_SSP ... MSR_IA32_PL3_SSP: + if (!guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK)) { + WARN_ON_ONCE(msr_info->index !=3D MSR_IA32_FRED_SSP0); + msr_info->data =3D vcpu->arch.fred_ssp0_fallback; + break; + } + kvm_get_xstate_msr(vcpu, msr_info); break; default: @@ -2656,10 +2730,19 @@ static void kvm_probe_msr_to_save(u32 msr_index) if (!kvm_cpu_cap_has(X86_FEATURE_LM)) return; fallthrough; - case MSR_IA32_PL0_SSP ... MSR_IA32_PL3_SSP: + case MSR_IA32_PL1_SSP ... MSR_IA32_PL3_SSP: if (!kvm_cpu_cap_has(X86_FEATURE_SHSTK)) return; break; + case MSR_IA32_FRED_RSP0 ... MSR_IA32_FRED_CONFIG: + if (!kvm_cpu_cap_has(X86_FEATURE_FRED)) + return; + break; + case MSR_IA32_PL0_SSP: /* I.e., MSR_IA32_FRED_SSP0 */ + if (!kvm_cpu_cap_has(X86_FEATURE_SHSTK) && + !kvm_cpu_cap_has(X86_FEATURE_FRED)) + return; + break; default: break; } diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index b6b73ab9cfb7..362bd4dda298 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -1489,6 +1489,18 @@ static void vmx_write_guest_kernel_gs_base(struct vc= pu_vmx *vmx, u64 data) vmx_write_guest_host_msr(vmx, MSR_KERNEL_GS_BASE, data, &vmx->msr_guest_kernel_gs_base); } + +static u64 vmx_read_guest_fred_rsp0(struct vcpu_vmx *vmx) +{ + return vmx_read_guest_host_msr(vmx, MSR_IA32_FRED_RSP0, + &vmx->msr_guest_fred_rsp0); +} + +static void vmx_write_guest_fred_rsp0(struct vcpu_vmx *vmx, u64 data) +{ + vmx_write_guest_host_msr(vmx, MSR_IA32_FRED_RSP0, data, + &vmx->msr_guest_fred_rsp0); +} #endif =20 static void grow_ple_window(struct kvm_vcpu *vcpu) @@ -2140,6 +2152,27 @@ int vmx_get_feature_msr(u32 msr, u64 *data) } } =20 +#ifdef CONFIG_X86_64 +static const u32 fred_msr_vmcs_fields[] =3D { + GUEST_IA32_FRED_RSP1, + GUEST_IA32_FRED_RSP2, + GUEST_IA32_FRED_RSP3, + GUEST_IA32_FRED_STKLVLS, + GUEST_IA32_FRED_SSP1, + GUEST_IA32_FRED_SSP2, + GUEST_IA32_FRED_SSP3, + GUEST_IA32_FRED_CONFIG, +}; + +static_assert(MSR_IA32_FRED_CONFIG - MSR_IA32_FRED_RSP1 =3D=3D + ARRAY_SIZE(fred_msr_vmcs_fields) - 1); + +static u32 fred_msr_to_vmcs(u32 msr) +{ + return fred_msr_vmcs_fields[msr - MSR_IA32_FRED_RSP1]; +} +#endif + /* * Reads an msr value (of 'msr_info->index') into 'msr_info->data'. * Returns 0 on success, non-0 otherwise. @@ -2162,6 +2195,12 @@ int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_da= ta *msr_info) case MSR_KERNEL_GS_BASE: msr_info->data =3D vmx_read_guest_kernel_gs_base(vmx); break; + case MSR_IA32_FRED_RSP0: + msr_info->data =3D vmx_read_guest_fred_rsp0(vmx); + break; + case MSR_IA32_FRED_RSP1 ... MSR_IA32_FRED_CONFIG: + msr_info->data =3D vmcs_read64(fred_msr_to_vmcs(msr_info->index)); + break; #endif case MSR_EFER: return kvm_get_msr_common(vcpu, msr_info); @@ -2394,6 +2433,12 @@ int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_da= ta *msr_info) vmx_update_exception_bitmap(vcpu); } break; + case MSR_IA32_FRED_RSP0: + vmx_write_guest_fred_rsp0(vmx, data); + break; + case MSR_IA32_FRED_RSP1 ... MSR_IA32_FRED_CONFIG: + vmcs_write64(fred_msr_to_vmcs(msr_index), data); + break; #endif case MSR_IA32_SYSENTER_CS: if (is_guest_mode(vcpu)) --=20 2.43.0 From nobody Fri Sep 25 13:16:55 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) (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 3C1B0486428; Fri, 11 Sep 2026 21:41:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162892; cv=none; b=AaIuY1o9UCGIS7BAHoHyY+UVqzeXSGO9sO6b811RXmknh3jo5DbB9u/b/Bp214iMx7rxFTOF/BdH76DMMJUd7PuOyRRdJlFstuJiBLKWY2KP8C4rYkMmAjsoXnoEkPujErgMNyjrFd+gVvawzvZnLBOt+DmIWfzx/LWYdIFGUAA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162892; c=relaxed/simple; bh=VH/Hb30LkkF1uNVw/5tny50cxjDCIA7BZaPXPxi93dU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QYpyQM/k7fDgqCRggS9Gp7a5vzXWb6OXw8Y0uLPTfDVrDgWsm1xQIAWmqDprPcu9KSMMonyUJFmBFiquc05b0L+Zb4tmYelKJ16LkPEr3rSPZols4Uj9M/ceQqy0g2O9PV14SVJmzQ+6W30od7mFD3Juu9zkR5l6OpolL0DnqnQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=SZzwkR2B; arc=none smtp.client-ip=192.198.163.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="SZzwkR2B" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789162891; x=1820698891; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=VH/Hb30LkkF1uNVw/5tny50cxjDCIA7BZaPXPxi93dU=; b=SZzwkR2BglRyvwiUcUXeX6Erd2p4i8oFWPkQtRnaHPYsnFY9pSC1Xvxe c10ECTnEUNgBBqOVG518RUwK7Mu3KCc3mD6PI5Nyv00gvq8v95O16Fn3Q S47WjsrhwAxWUFJuHr4DyTZXSHMmLZ7bIUjjfIYlPGj8Bkroj/+hHkTew L/qvagE96jxAPqDxhSUc1D2CBUtXiXhReOCCuA73ggw+YVqxO7loRotuA AP1nXI1vVWM8CGXjxjGzrsVPYha2YvjcXyDQK0s9BwL+ODh4lO7XlINxr Mjqq/ZnAsko9qFZijZu3/IxOUusEdjeE09t/IxrOifG0k8UxTx3pm6I1C Q==; X-CSE-ConnectionGUID: zbV+qPWzTmiJBgLQRFTHng== X-CSE-MsgGUID: Rih6FkkVRBiKoiu1xnhA5A== X-IronPort-AV: E=McAfee;i="6800,10657,11902"; a="88572611" X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="88572611" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Sep 2026 14:41:30 -0700 X-CSE-ConnectionGUID: HH6JC9v4QHOFKi0L69m4Aw== X-CSE-MsgGUID: WdAjvVEkRDSJu1yi7kuTTQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="272004078" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa007.jf.intel.com with ESMTP; 11 Sep 2026 14:41:29 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Paolo Bonzini , Sean Christopherson , Jonathan Corbet , Shuah Khan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Xin Li , Andy Lutomirski , Peter Zijlstra , Andrew Cooper , Tom Lendacky , Nikunj A Dadhania , Shivansh Dhiman , David Woodhouse , Chao Gao , Binbin Wu , Sohil Mehta , Zhao Liu , Yosry Ahmed , David Matlack , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v10 11/28] KVM: x86: Add a helper to detect if FRED is enabled for a vCPU Date: Fri, 11 Sep 2026 14:36:41 -0700 Message-ID: <20260911213659.2025974-12-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260911213659.2025974-1-sohil.mehta@intel.com> References: <20260911213659.2025974-1-sohil.mehta@intel.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 (Intel)" Add is_fred_enabled() to detect if FRED is enabled on a vCPU. Signed-off-by: Xin Li (Intel) [ Sean: removed the "kvm_" prefix from the function name ] Signed-off-by: Sean Christopherson Signed-off-by: Sohil Mehta Tested-by: Shan Kang Tested-by: Xuelian Guo Reviewed-by: Chao Gao --- v10: - Add back the change log (Binbin Wu and Sean). --- arch/x86/kvm/regs.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/x86/kvm/regs.h b/arch/x86/kvm/regs.h index 447f0ec3e63e..4e641a6c20f9 100644 --- a/arch/x86/kvm/regs.h +++ b/arch/x86/kvm/regs.h @@ -364,6 +364,21 @@ static __always_inline bool kvm_is_cr4_bit_set(struct = kvm_vcpu *vcpu, return !!kvm_read_cr4_bits(vcpu, cr4_bit); } =20 +/* + * It's enough to check just CR4.FRED (X86_CR4_FRED) to tell if + * a vCPU is running with FRED enabled, because: + * 1) CR4.FRED can be set to 1 only _after_ IA32_EFER.LMA =3D 1. + * 2) To leave IA-32e mode, CR4.FRED must be cleared first. + */ +static inline bool is_fred_enabled(struct kvm_vcpu *vcpu) +{ +#ifdef CONFIG_X86_64 + return kvm_is_cr4_bit_set(vcpu, X86_CR4_FRED); +#else + return false; +#endif +} + static inline ulong kvm_read_cr3(struct kvm_vcpu *vcpu) { if (!kvm_register_is_available(vcpu, VCPU_REG_CR3)) --=20 2.43.0 From nobody Fri Sep 25 13:16:55 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) (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 ED3A646C830; Fri, 11 Sep 2026 21:41:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162900; cv=none; b=TaWFQj/vOqU1DG+s/6ZrS09LCDUTKxEngu0eUpJA46mOIKAgoERxQeihmmZLuoteAsLYuePh309M1jsidQKXJLBDGjFus9qzQfK3os0YYySs4RYnQgpM6PsXD+nEnOWquQ065/cfD6xi+rebhP+vrV2BHiJi6topQUL6SEJVs9A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162900; c=relaxed/simple; bh=7ETT34uBFBm6rxlUmHDQWKjIjRP+Dbp9dWzkfkSPA8Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=M8gOlLLqkC6JNThxa8rYCNtT8o79dMVNy2+FbFcgITppq4FlBJo2jTSWVz80lZlY09VJLJrlojKD3q03yki4I2jLfJvXHtmcZGz5Va+N9v9MQbGEsg5y3mf680qZWFFfyYBvH0vaiADCRwboBf6wUPweHkIIEWZhCpSatHHeaGI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=QGmrzaga; arc=none smtp.client-ip=192.198.163.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="QGmrzaga" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789162899; x=1820698899; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=7ETT34uBFBm6rxlUmHDQWKjIjRP+Dbp9dWzkfkSPA8Q=; b=QGmrzagaTCbynGCxlybRR3nOSt+31o/c7MSVyu/vHlC5sfL+4iQTB5ES iFhhPkw6YD8G420l79QPdx1GSiNa7cocWr/2BaLpZpz8sD6Ol6J26Aiik ShxllDKpANalkx6qZYSpb4Zvn4HDAaXFjPiOI+wNtseROk/4wlhnY3S5w no0hjQEMkPQIgi97TPSJEYGtd0o9IMRwvQ35USaofvkyG4501G6w+IlXX 74NWDVuQpCRWbIphNke1x/VfeasPacYu7O+i2ts1ANjYGS+nCGpOh4sZr U+81qRh3jJJt0o7BL3x37LdKpFdNz38mTQUi9o0Qy2ZFXkdv1V0U/qr01 g==; X-CSE-ConnectionGUID: 8VnF58YdQ86q1bR60EvtBw== X-CSE-MsgGUID: WQQcQrhxSmmMp7FNE+BsJw== X-IronPort-AV: E=McAfee;i="6800,10657,11902"; a="88572649" X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="88572649" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Sep 2026 14:41:38 -0700 X-CSE-ConnectionGUID: DzCUGsU8St6LgzASWN70cQ== X-CSE-MsgGUID: qZZuu7lUR4C7zUalgkEtXQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="272004109" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa007.jf.intel.com with ESMTP; 11 Sep 2026 14:41:37 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Paolo Bonzini , Sean Christopherson , Jonathan Corbet , Shuah Khan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Xin Li , Andy Lutomirski , Peter Zijlstra , Andrew Cooper , Tom Lendacky , Nikunj A Dadhania , Shivansh Dhiman , David Woodhouse , Chao Gao , Binbin Wu , Sohil Mehta , Zhao Liu , Yosry Ahmed , David Matlack , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v10 12/28] KVM: x86: Add a new save/restore flag for FRED metadata Date: Fri, 11 Sep 2026 14:36:42 -0700 Message-ID: <20260911213659.2025974-13-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260911213659.2025974-1-sohil.mehta@intel.com> References: <20260911213659.2025974-1-sohil.mehta@intel.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 Introduce a new save/restore flag for FRED metadata (specifically, the event nested flag and data) being saved and restored during VM save/ restore and live migration. Signed-off-by: Xin Li Signed-off-by: Sohil Mehta --- v10: - Advertise KVM_CAP_X86_FRED_EVENT only when KVM can virtualize FRED, and return -EINVAL from KVM_ENABLE_CAP otherwise. - Document the new return value in api.rst. --- Documentation/virt/kvm/api.rst | 22 ++++++++++++++++++++++ arch/x86/include/asm/kvm_host.h | 1 + arch/x86/include/uapi/asm/kvm.h | 1 + arch/x86/kvm/x86.c | 18 ++++++++++++++++++ include/uapi/linux/kvm.h | 1 + 5 files changed, 43 insertions(+) diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst index 4eb7e75a7473..22ef94f3eb3a 100644 --- a/Documentation/virt/kvm/api.rst +++ b/Documentation/virt/kvm/api.rst @@ -1199,6 +1199,10 @@ The following bits are defined in the flags field: triple_fault_pending field contains a valid state. This bit will be set whenever KVM_CAP_X86_TRIPLE_FAULT_EVENT is enabled. =20 +- KVM_VCPUEVENT_VALID_FRED_STATE may be set to inform that the exception + state includes FRED state (specifically, the event nested flag and data). + This bit will be set whenever KVM_CAP_X86_FRED_EVENT is enabled. + ARM64: ^^^^^^ =20 @@ -1301,6 +1305,11 @@ If KVM_CAP_X86_TRIPLE_FAULT_EVENT is enabled, KVM_VC= PUEVENT_VALID_TRIPLE_FAULT can be set in flags field to signal that the triple_fault field contains a valid state and shall be written into the VCPU. =20 +If KVM_CAP_X86_FRED_EVENT is enabled, KVM_VCPUEVENT_VALID_FRED_STATE can b= e set +in the flags field to inform that the exception state contains FRED state +(specifically, the event nested flag and data), which shall be written int= o the +VCPU. + ARM64: ^^^^^^ =20 @@ -8979,6 +8988,19 @@ enabled, cmma can't be enabled anymore and pfmfi and= the storage key interpretation are disabled. If cmma has already been enabled or the hpage_2g module parameter is not set to 1, -EINVAL is returned. =20 +7.48 KVM_CAP_X86_FRED_EVENT +--------------------------- + +:Architectures: x86 +:Parameters: args[0] whether feature should be enabled or not +:Returns: 0 on success; -EINVAL if KVM cannot virtualize FRED. + +With this capability enabled, KVM allows exception save and restore operat= ions +to include FRED event context (specifically, the event nested flag and dat= a). +When injecting a FRED exception during VM entry, FRED event delivery relies +on this information to select the correct event stack level and apply prop= er +event data. + 8. Other capabilities. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index 0fd5d4edeebb..dd68db17fdae 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1286,6 +1286,7 @@ struct kvm_arch { bool has_mapped_host_mmio; bool guest_can_read_msr_platform_info; bool exception_payload_enabled; + bool exception_fred_state_enabled; =20 bool triple_fault_event; =20 diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kv= m.h index 1585ec804066..6a67832c59bb 100644 --- a/arch/x86/include/uapi/asm/kvm.h +++ b/arch/x86/include/uapi/asm/kvm.h @@ -331,6 +331,7 @@ struct kvm_reinject_control { #define KVM_VCPUEVENT_VALID_SMM 0x00000008 #define KVM_VCPUEVENT_VALID_PAYLOAD 0x00000010 #define KVM_VCPUEVENT_VALID_TRIPLE_FAULT 0x00000020 +#define KVM_VCPUEVENT_VALID_FRED_STATE 0x00000040 =20 /* Interrupt shadow states */ #define KVM_X86_SHADOW_INT_MOV_SS 0x01 diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 4b3681796c75..01198aba27cf 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2288,6 +2288,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, lon= g ext) case KVM_CAP_PRE_FAULT_MEMORY: r =3D tdp_enabled; break; + case KVM_CAP_X86_FRED_EVENT: + r =3D kvm_cpu_cap_has(X86_FEATURE_FRED); + break; case KVM_CAP_X86_APIC_BUS_CYCLES_NS: r =3D kvm ? kvm->arch.apic_bus_cycle_ns : APIC_BUS_CYCLE_NS_DEFAULT; break; @@ -3022,6 +3025,8 @@ static void kvm_vcpu_ioctl_x86_get_vcpu_events(struct= kvm_vcpu *vcpu, | KVM_VCPUEVENT_VALID_SMM); if (vcpu->kvm->arch.exception_payload_enabled) events->flags |=3D KVM_VCPUEVENT_VALID_PAYLOAD; + if (vcpu->kvm->arch.exception_fred_state_enabled) + events->flags |=3D KVM_VCPUEVENT_VALID_FRED_STATE; if (vcpu->kvm->arch.triple_fault_event) { events->triple_fault.pending =3D kvm_test_request(KVM_REQ_TRIPLE_FAULT, = vcpu); events->flags |=3D KVM_VCPUEVENT_VALID_TRIPLE_FAULT; @@ -3036,6 +3041,7 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct = kvm_vcpu *vcpu, | KVM_VCPUEVENT_VALID_SHADOW | KVM_VCPUEVENT_VALID_SMM | KVM_VCPUEVENT_VALID_PAYLOAD + | KVM_VCPUEVENT_VALID_FRED_STATE | KVM_VCPUEVENT_VALID_TRIPLE_FAULT)) return -EINVAL; =20 @@ -3051,6 +3057,11 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct= kvm_vcpu *vcpu, events->exception_has_payload =3D 0; } =20 + if (events->flags & KVM_VCPUEVENT_VALID_FRED_STATE) { + if (!vcpu->kvm->arch.exception_fred_state_enabled) + return -EINVAL; + } + if ((events->exception.injected || events->exception.pending) && (events->exception.nr > 31 || events->exception.nr =3D=3D NMI_VECTOR)) return -EINVAL; @@ -4038,6 +4049,13 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm, kvm->arch.exception_payload_enabled =3D cap->args[0]; r =3D 0; break; + case KVM_CAP_X86_FRED_EVENT: + r =3D -EINVAL; + if (!kvm_cpu_cap_has(X86_FEATURE_FRED)) + break; + kvm->arch.exception_fred_state_enabled =3D cap->args[0]; + r =3D 0; + break; case KVM_CAP_X86_TRIPLE_FAULT_EVENT: kvm->arch.triple_fault_event =3D cap->args[0]; r =3D 0; diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 9fc8dfdfd65f..c5ffc4e7ddb1 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -998,6 +998,7 @@ struct kvm_enable_cap { #define KVM_CAP_S390_VSIE_ESAMODE 248 #define KVM_CAP_S390_HPAGE_2G 249 #define KVM_CAP_ARM_PMU_V3_STRICT 250 +#define KVM_CAP_X86_FRED_EVENT 251 =20 struct kvm_irq_routing_irqchip { __u32 irqchip; --=20 2.43.0 From nobody Fri Sep 25 13:16:55 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) (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 7E52448663E; Fri, 11 Sep 2026 21:41:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162912; cv=none; b=f7hUDaviZ6iL0xJFE2UgZy9s8DZ2K3WxK4IiaqyypbjvctG2bdewC1u9RmmQ2tfqQHRj36UbxSMBqkvGHNAoxKB81L0X3NYTi9kNIpKBEkgCWpdFx0Gca/AIoadqzuLv1Ea2GYMxbXCGJxUU5C8kKceUnHg8poGq0m6yNqNJOsg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162912; c=relaxed/simple; bh=4xf8GdYdyRjE4wumPq1FX/osIPlad31Ti2Ie9a9xTWI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bX5mhbx0zDK16on8g7OQwRtx6N+ebUU+4kgHkME3g08IzNYzZDzWGMF+u26CEuPHTQhiixl4PpV4LWFsIZJZxV1KHVKXy4mlKplOCwwHYLYF9sg93NLGs8d6nWFriHZ3YM118Z6SW5QPTJ1O1f9AtxT3u+BBSio78dL4LApPPH8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=B5nJU1WT; arc=none smtp.client-ip=192.198.163.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="B5nJU1WT" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789162911; x=1820698911; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=4xf8GdYdyRjE4wumPq1FX/osIPlad31Ti2Ie9a9xTWI=; b=B5nJU1WTeG86t54ORZYy8ouH/WBvFe/0olt1FLyoaPO0b/3tZG0fin9g h19Yy7ocAnw/2Ja6N6jBg+bNyMdPZTeJoCXwhhYqjsee6HY0bWv7iskTN uGMTe5ZWxqzBs7rV7e/S7gfJyTohmW1DQckywFgrNSXXQIF++KZeThn65 v7GRrkjTrZRlInOfsKBeT8tPjqd9x5yfuUV5zO94NbEbRT2q3JVznvC0Z Eg56XmKdIuDL+3MVd2wYxWM6JcTdxXdjqXWclJOdBUulMIVAMYpBSpUVE JU7QkAjnZmJjGf6jv9mJ+q3IabnAJUYSlW2YcY6G9hjwpnqPb3ONVq04p g==; X-CSE-ConnectionGUID: yvToJSKoTlmG1/q7nIVRgA== X-CSE-MsgGUID: kgiB825CQYuKbVyeARYanQ== X-IronPort-AV: E=McAfee;i="6800,10657,11902"; a="88572689" X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="88572689" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Sep 2026 14:41:50 -0700 X-CSE-ConnectionGUID: dZnMJZAPRtmUJ/nrw+yVFQ== X-CSE-MsgGUID: g9gVpPMQTAK5lsBH0PpPRQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="272004130" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa007.jf.intel.com with ESMTP; 11 Sep 2026 14:41:49 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Paolo Bonzini , Sean Christopherson , Jonathan Corbet , Shuah Khan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Xin Li , Andy Lutomirski , Peter Zijlstra , Andrew Cooper , Tom Lendacky , Nikunj A Dadhania , Shivansh Dhiman , David Woodhouse , Chao Gao , Binbin Wu , Sohil Mehta , Zhao Liu , Yosry Ahmed , David Matlack , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v10 13/28] KVM: VMX: Virtualize FRED nested exception tracking Date: Fri, 11 Sep 2026 14:36:43 -0700 Message-ID: <20260911213659.2025974-14-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260911213659.2025974-1-sohil.mehta@intel.com> References: <20260911213659.2025974-1-sohil.mehta@intel.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 (Intel)" Set the VMX nested exception bit in VM-entry interruption information field when injecting a nested exception using FRED event delivery to ensure: 1) A nested exception is injected on a correct stack level. 2) The nested bit defined in FRED stack frame is set. The event stack level used by FRED event delivery depends on whether the event was a nested exception encountered during delivery of an earlier event, because a nested exception is "regarded" as happening on ring 0. E.g., when #PF is configured to use stack level 1 in IA32_FRED_STKLVLS MSR: - nested #PF will be delivered on the stack pointed by IA32_FRED_RSP1 MSR when encountered in ring 3 and ring 0. - normal #PF will be delivered on the stack pointed by IA32_FRED_RSP0 MSR when encountered in ring 3. The VMX nested-exception support ensures a correct event stack level is chosen when a VM entry injects a nested exception. In addition, save/restore the nested flag of an exception during VM save/restore and live migration to ensure a correct event stack level is chosen when a nested exception is injected through FRED event delivery across VM save/restore and live migration. Note, like the other fields of struct kvm_queued_exception, the nested flag is meaningful only while the exception is pending or injected. It is not consulted otherwise, and so doesn't need to be cleared when an exception is dropped. Signed-off-by: Xin Li (Intel) [ Sean: reworked kvm_requeue_exception() to simply the code changes ] Signed-off-by: Sean Christopherson Signed-off-by: Sohil Mehta Reviewed-by: Chao Gao --- v10: - Rename exception status member variable nested to is_nested (Sean). - Rename KVM_CAP_EXCEPTION_NESTED_FLAG to KVM_CAP_X86_FRED_EVENT, to include both FRED event nested flag and data. - Track the nested flag of an exception being queued in a local variable (so that a flag left over from a no-longer-live exception can't be folded into a new one). --- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/include/asm/vmx.h | 5 ++++- arch/x86/include/uapi/asm/kvm.h | 3 ++- arch/x86/kvm/svm/svm.c | 2 +- arch/x86/kvm/vmx/vmx.c | 10 ++++++++-- arch/x86/kvm/x86.c | 18 +++++++++++++++++- arch/x86/kvm/x86.h | 4 +++- 7 files changed, 36 insertions(+), 7 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index dd68db17fdae..994c354dc47b 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -695,6 +695,7 @@ struct kvm_queued_exception { u32 error_code; unsigned long payload; bool has_payload; + bool is_nested; }; =20 /* diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h index 4720619f09ac..7eb08f84a7e5 100644 --- a/arch/x86/include/asm/vmx.h +++ b/arch/x86/include/asm/vmx.h @@ -152,6 +152,7 @@ struct vmcs { #define VMX_BASIC_INOUT BIT_ULL(54) #define VMX_BASIC_TRUE_CTLS BIT_ULL(55) #define VMX_BASIC_NO_HW_ERROR_CODE_CC BIT_ULL(56) +#define VMX_BASIC_NESTED_EXCEPTION BIT_ULL(58) #define VMX_BASIC_NO_SEAMRET_INVD_VMCS BIT_ULL(60) =20 static inline u32 vmx_basic_vmcs_revision_id(u64 vmx_basic) @@ -451,13 +452,15 @@ enum vmcs_field { #define INTR_INFO_INTR_TYPE_MASK 0x700 /* 10:8 */ #define INTR_INFO_DELIVER_CODE_MASK 0x800 /* 11 */ #define INTR_INFO_UNBLOCK_NMI 0x1000 /* 12 */ +#define INTR_INFO_NESTED_EXCEPTION_MASK 0x2000 /* 13 */ #define INTR_INFO_VALID_MASK 0x80000000 /* 31 */ -#define INTR_INFO_RESVD_BITS_MASK 0x7ffff000 +#define INTR_INFO_RESVD_BITS_MASK 0x7fffd000 =20 #define VECTORING_INFO_VECTOR_MASK INTR_INFO_VECTOR_MASK #define VECTORING_INFO_TYPE_MASK INTR_INFO_INTR_TYPE_MASK #define VECTORING_INFO_DELIVER_CODE_MASK INTR_INFO_DELIVER_CODE_MASK #define VECTORING_INFO_VALID_MASK INTR_INFO_VALID_MASK +#define VECTORING_INFO_NESTED_EXCEPTION_MASK INTR_INFO_NESTED_EXCEPTION_MA= SK =20 #define INTR_TYPE_EXT_INTR (EVENT_TYPE_EXTINT << 8) /* external interrupt= */ #define INTR_TYPE_RESERVED (EVENT_TYPE_RESERVED << 8) /* reserved */ diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kv= m.h index 6a67832c59bb..659c8391d40e 100644 --- a/arch/x86/include/uapi/asm/kvm.h +++ b/arch/x86/include/uapi/asm/kvm.h @@ -369,7 +369,8 @@ struct kvm_vcpu_events { struct { __u8 pending; } triple_fault; - __u8 reserved[26]; + __u8 reserved[25]; + __u8 exception_is_nested; __u8 exception_has_payload; __u64 exception_payload; }; diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index ea647938a2a6..7762db655b28 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -4392,7 +4392,7 @@ static void svm_complete_interrupts(struct kvm_vcpu *= vcpu) =20 kvm_requeue_exception(vcpu, vector, exitintinfo & SVM_EXITINTINFO_VALID_ERR, - error_code); + error_code, false); break; } case SVM_EXITINTINFO_TYPE_INTR: diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 362bd4dda298..25c3301e137b 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -2008,8 +2008,13 @@ void vmx_inject_exception(struct kvm_vcpu *vcpu) vmcs_write32(VM_ENTRY_INSTRUCTION_LEN, vmx->vcpu.arch.event_exit_inst_len); intr_info |=3D INTR_TYPE_SOFT_EXCEPTION; - } else + } else { intr_info |=3D INTR_TYPE_HARD_EXCEPTION; + if (is_fred_enabled(vcpu)) { + if (ex->is_nested) + intr_info |=3D INTR_INFO_NESTED_EXCEPTION_MASK; + } + } =20 vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr_info); =20 @@ -7501,7 +7506,8 @@ static void __vmx_complete_interrupts(struct kvm_vcpu= *vcpu, =20 kvm_requeue_exception(vcpu, vector, idt_vectoring_info & VECTORING_INFO_DELIVER_CODE_MASK, - error_code); + error_code, + idt_vectoring_info & VECTORING_INFO_NESTED_EXCEPTION_MASK); break; } case INTR_TYPE_SOFT_INTR: diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 01198aba27cf..94d684210cf6 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -461,6 +461,7 @@ static void kvm_multiple_exception(struct kvm_vcpu *vcp= u, unsigned int nr, bool has_error, u32 error_code, bool has_payload, unsigned long payload) { + bool is_nested =3D false; u32 prev_nr; int class1, class2; =20 @@ -487,6 +488,11 @@ static void kvm_multiple_exception(struct kvm_vcpu *vc= pu, unsigned int nr, vcpu->arch.exception.error_code =3D error_code; vcpu->arch.exception.has_payload =3D has_payload; vcpu->arch.exception.payload =3D payload; + /* #DF is NOT a nested event, per its definition. */ + vcpu->arch.exception.is_nested =3D (nr !=3D DF_VECTOR) && + (is_nested || + vcpu->arch.nmi_injected || + vcpu->arch.interrupt.injected); return; } =20 @@ -510,6 +516,9 @@ static void kvm_multiple_exception(struct kvm_vcpu *vcp= u, unsigned int nr, =20 kvm_queue_exception_e(vcpu, DF_VECTOR, 0); } else { + /* The new exception arrived while delivering the previous one. */ + is_nested =3D true; + /* replace previous exception with a new one in a hope that instruction re-execution will regenerate lost exception */ @@ -538,7 +547,8 @@ static void kvm_queue_exception_e_p(struct kvm_vcpu *vc= pu, unsigned nr, } =20 void kvm_requeue_exception(struct kvm_vcpu *vcpu, unsigned int nr, - bool has_error_code, u32 error_code) + bool has_error_code, u32 error_code, + bool is_nested) { =20 /* @@ -563,6 +573,7 @@ void kvm_requeue_exception(struct kvm_vcpu *vcpu, unsig= ned int nr, vcpu->arch.exception.error_code =3D error_code; vcpu->arch.exception.has_payload =3D false; vcpu->arch.exception.payload =3D 0; + vcpu->arch.exception.is_nested =3D is_nested; } EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_requeue_exception); =20 @@ -3000,6 +3011,7 @@ static void kvm_vcpu_ioctl_x86_get_vcpu_events(struct= kvm_vcpu *vcpu, events->exception.error_code =3D ex->error_code; events->exception_has_payload =3D ex->has_payload; events->exception_payload =3D ex->payload; + events->exception_is_nested =3D ex->is_nested; =20 events->interrupt.injected =3D vcpu->arch.interrupt.injected && !vcpu->arch.interrupt.soft; @@ -3060,6 +3072,8 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct = kvm_vcpu *vcpu, if (events->flags & KVM_VCPUEVENT_VALID_FRED_STATE) { if (!vcpu->kvm->arch.exception_fred_state_enabled) return -EINVAL; + } else { + events->exception_is_nested =3D 0; } =20 if ((events->exception.injected || events->exception.pending) && @@ -3087,6 +3101,7 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct = kvm_vcpu *vcpu, vcpu->arch.exception.error_code =3D events->exception.error_code; vcpu->arch.exception.has_payload =3D events->exception_has_payload; vcpu->arch.exception.payload =3D events->exception_payload; + vcpu->arch.exception.is_nested =3D events->exception_is_nested; =20 vcpu->arch.interrupt.injected =3D events->interrupt.injected; vcpu->arch.interrupt.nr =3D events->interrupt.nr; @@ -8978,6 +8993,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) ex->has_payload, ex->payload); ex->injected =3D false; ex->pending =3D false; + ex->is_nested =3D false; } vcpu->arch.exception_from_userspace =3D false; =20 diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index 0f5919b092e4..2d6bae66cfae 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -158,6 +158,7 @@ static inline void kvm_clear_exception_queue(struct kvm= _vcpu *vcpu) { vcpu->arch.exception.pending =3D false; vcpu->arch.exception.injected =3D false; + vcpu->arch.exception.is_nested =3D false; vcpu->arch.exception_vmexit.pending =3D false; } =20 @@ -502,7 +503,8 @@ void kvm_queue_exception(struct kvm_vcpu *vcpu, unsigne= d nr); void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_c= ode); void kvm_queue_exception_p(struct kvm_vcpu *vcpu, unsigned nr, unsigned lo= ng payload); void kvm_requeue_exception(struct kvm_vcpu *vcpu, unsigned int nr, - bool has_error_code, u32 error_code); + bool has_error_code, u32 error_code, + bool is_nested); void kvm_inject_page_fault(struct kvm_vcpu *vcpu, struct x86_exception *fa= ult, bool from_hardware); void __kvm_inject_emulated_page_fault(struct kvm_vcpu *vcpu, --=20 2.43.0 From nobody Fri Sep 25 13:16:55 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) (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 D332E486428; Fri, 11 Sep 2026 21:42:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162924; cv=none; b=So7YSo+g7lJTj4SEC6F9jS8nwYjJz093v4zvQPRlis720kyFv1sjzo16Vdy+5XMv8KmI5lNoreLSGFVXKmxvn1DuuatHJiEy/yXAx9BoYITVpqDG4FGwTvHU7NvgI6CMZ1tEQrezfh+UeyjCPDwVGQIBsNbABmT2PEX1Mc83fjE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162924; c=relaxed/simple; bh=xUcMDZDichUi5tjRck2N6+/wFdKZRiuD+AU5NNUOLQo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jcwSq2hZV10ejPyBhgrCj7wus6hXF2EgZ8YrZS3OwcOZfz/Itn2o50H3iOFAI1dW58Z9rH53CaoG5fIwnyT+i5v2mhdMJVxwdz4rs/SGaXHK6jXIPmZ1kGS3ibAsaR+KZv3S1olglPSC+SGFjIA7iU3AwHCIn8sewKrRYKnVLlM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=SjOyPrkl; arc=none smtp.client-ip=192.198.163.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="SjOyPrkl" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789162922; x=1820698922; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=xUcMDZDichUi5tjRck2N6+/wFdKZRiuD+AU5NNUOLQo=; b=SjOyPrklOzSeu+2paPmha9nh4rqLe38XBgUjcyvRtcAj1GAORrISUNq8 HZPwtyuk17X6CWkqZGYE8AVq29IOoW0YH0cpnJKLxyy+9CrKYXlh3yEKO X3pYA7kvAIzZAhUtcguAwzFr8ach0t/a+k7h5sEXB3AqAsMoLmGclnejg y18CKNT9cuVkh0XvUAZ/9dx89JRmmJPRF+nNg60jiSnBruBLF/6zFMDI3 r7TNh6GOvO0XxVGuLx3HxwUpAIxkbDP3ixHq8EM7Its3MupdFHhlEuuZ5 XdB7G41sGizc45BbDjBv/TC1E+Ptlayr8187zoLuOhGqVBfHQn4jq2JrX Q==; X-CSE-ConnectionGUID: E2pOVRkDROWh0VmV4ZZrmQ== X-CSE-MsgGUID: rbu1enZOSNSXmjBmVma0Rg== X-IronPort-AV: E=McAfee;i="6800,10657,11902"; a="88572702" X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="88572702" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Sep 2026 14:42:01 -0700 X-CSE-ConnectionGUID: aBj4wUqaTwy2vLRLgK/Tqg== X-CSE-MsgGUID: gI9yXVjhQ0GFX89L0zSaCA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="272004153" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa007.jf.intel.com with ESMTP; 11 Sep 2026 14:42:01 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Paolo Bonzini , Sean Christopherson , Jonathan Corbet , Shuah Khan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Xin Li , Andy Lutomirski , Peter Zijlstra , Andrew Cooper , Tom Lendacky , Nikunj A Dadhania , Shivansh Dhiman , David Woodhouse , Chao Gao , Binbin Wu , Sohil Mehta , Zhao Liu , Yosry Ahmed , David Matlack , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v10 14/28] KVM: VMX: Virtualize FRED event_data Date: Fri, 11 Sep 2026 14:36:44 -0700 Message-ID: <20260911213659.2025974-15-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260911213659.2025974-1-sohil.mehta@intel.com> References: <20260911213659.2025974-1-sohil.mehta@intel.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 (Intel)" Set injected-event data when injecting a #PF, #DB, or #NM due to extended feature disable using FRED event delivery, and save original-event data for being used as injected-event data. Unlike IDT using some extra CPU register as part of an event context, e.g., %cr2 for #PF, FRED saves a complete event context in its stack frame, e.g., FRED saves the faulting linear address of a #PF into the event data field defined in its stack frame. Thus a new VMX control field called injected-event data is added to provide the event data that will be pushed into a FRED stack frame for VM entries that inject an event using FRED event delivery. In addition, a new VM exit information field called original-event data is added to store the event data that would have saved into a FRED stack frame for VM exits that occur during FRED event delivery. After such a VM exit is handled to allow the original-event to be delivered, the data in the original-event data VMCS field needs to be set into the injected-event data VMCS field for the injection of the original event. In addition, save/restore the event data of an exception during VM save/restore and live migration to ensure it's properly saved and restored across VM save/restore and live migration. Clear the injected-event data field when injecting an IRQ or an NMI as no event data is currently defined for them. Signed-off-by: Xin Li (Intel) [ Sean: reworked event data injection for nested ] Signed-off-by: Sean Christopherson Signed-off-by: Sohil Mehta --- v10: - Reset event data in kvm_clear_exception_queue() (Chao). - Clear event data to 0 to prevent stale data leakage when injecting a hardware exception that doesn't require FRED event data. - Save/restore event data for properly restoring it for #PF (CR2), #DB (DR6) and #NM due to extended feature disable (IA32_XFD_ERR) (Chao). - Clear the INJECTED_EVENT_DATA VMCS field during NMI and IRQ injection. (Zhao) --- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/include/asm/vmx.h | 4 +++ arch/x86/include/uapi/asm/kvm.h | 5 ++- arch/x86/kvm/svm/svm.c | 2 +- arch/x86/kvm/vmx/vmx.c | 58 ++++++++++++++++++++++++++++++--- arch/x86/kvm/x86.c | 23 ++++++++++++- arch/x86/kvm/x86.h | 3 +- 7 files changed, 88 insertions(+), 8 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index 994c354dc47b..21d12d86a18b 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -696,6 +696,7 @@ struct kvm_queued_exception { unsigned long payload; bool has_payload; bool is_nested; + u64 event_data; }; =20 /* diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h index 7eb08f84a7e5..6633988a84da 100644 --- a/arch/x86/include/asm/vmx.h +++ b/arch/x86/include/asm/vmx.h @@ -283,8 +283,12 @@ enum vmcs_field { PID_POINTER_TABLE_HIGH =3D 0x00002043, SECONDARY_VM_EXIT_CONTROLS =3D 0x00002044, SECONDARY_VM_EXIT_CONTROLS_HIGH =3D 0x00002045, + INJECTED_EVENT_DATA =3D 0x00002052, + INJECTED_EVENT_DATA_HIGH =3D 0x00002053, GUEST_PHYSICAL_ADDRESS =3D 0x00002400, GUEST_PHYSICAL_ADDRESS_HIGH =3D 0x00002401, + ORIGINAL_EVENT_DATA =3D 0x00002404, + ORIGINAL_EVENT_DATA_HIGH =3D 0x00002405, VMCS_LINK_POINTER =3D 0x00002800, VMCS_LINK_POINTER_HIGH =3D 0x00002801, GUEST_IA32_DEBUGCTL =3D 0x00002802, diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kv= m.h index 659c8391d40e..c8a6149fcf63 100644 --- a/arch/x86/include/uapi/asm/kvm.h +++ b/arch/x86/include/uapi/asm/kvm.h @@ -369,7 +369,10 @@ struct kvm_vcpu_events { struct { __u8 pending; } triple_fault; - __u8 reserved[25]; + __u8 reserved0[11]; + /* Aligned to a 64-bit boundary */ + __u64 exception_event_data; + __u8 reserved1[6]; __u8 exception_is_nested; __u8 exception_has_payload; __u64 exception_payload; diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 7762db655b28..f254a5ff570d 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -4392,7 +4392,7 @@ static void svm_complete_interrupts(struct kvm_vcpu *= vcpu) =20 kvm_requeue_exception(vcpu, vector, exitintinfo & SVM_EXITINTINFO_VALID_ERR, - error_code, false); + error_code, false, 0); break; } case SVM_EXITINTINFO_TYPE_INTR: diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 25c3301e137b..cd041381b322 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -2004,15 +2004,39 @@ void vmx_inject_exception(struct kvm_vcpu *vcpu) =20 WARN_ON_ONCE(vmx->vt.emulation_required); =20 + /* + * Event data is strictly required only for #PF, #DB, and #NM (due to + * extended feature disable) hardware exceptions under FRED, making it + * straightforward to correctly populate for just these vectors. + * + * Conversely, trying to guarantee that event data is cleanly managed or + * zeroed out across all other exception paths is highly complicated + * and error-prone. A blanket fallback to 0 handles those cases safely. + * + * Therefore, set INJECTED_EVENT_DATA only if all the following are true: + * - Guest has FRED enabled. + * - Exception type is a hardware exception. + * - Exception vector is #PF, #DB, or #NM. + * + * Otherwise, clear it to 0 to prevent stale data leakage. + */ if (kvm_exception_is_soft(ex->vector)) { vmcs_write32(VM_ENTRY_INSTRUCTION_LEN, vmx->vcpu.arch.event_exit_inst_len); intr_info |=3D INTR_TYPE_SOFT_EXCEPTION; + if (is_fred_enabled(vcpu)) + vmcs_write64(INJECTED_EVENT_DATA, 0); } else { intr_info |=3D INTR_TYPE_HARD_EXCEPTION; if (is_fred_enabled(vcpu)) { if (ex->is_nested) intr_info |=3D INTR_INFO_NESTED_EXCEPTION_MASK; + if (ex->vector =3D=3D PF_VECTOR || + ex->vector =3D=3D DB_VECTOR || + ex->vector =3D=3D NM_VECTOR) + vmcs_write64(INJECTED_EVENT_DATA, ex->event_data); + else + vmcs_write64(INJECTED_EVENT_DATA, 0); } } =20 @@ -5328,6 +5352,14 @@ void vmx_inject_irq(struct kvm_vcpu *vcpu, bool rein= jected) vmx->vcpu.arch.event_exit_inst_len); } else intr |=3D INTR_TYPE_EXT_INTR; + + /* + * Interrupts define no event data, so clear any value left behind + * by a previously injected exception. + */ + if (is_fred_enabled(vcpu)) + vmcs_write64(INJECTED_EVENT_DATA, 0); + vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr); =20 vmx_clear_hlt(vcpu); @@ -5358,6 +5390,13 @@ void vmx_inject_nmi(struct kvm_vcpu *vcpu) return; } =20 + /* + * KVM doesn't virtualize the NMI-source reporting feature. So clear + * any value left behind by a previously injected exception. + */ + if (is_fred_enabled(vcpu)) + vmcs_write64(INJECTED_EVENT_DATA, 0); + vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK | NMI_VECTOR); =20 @@ -7465,7 +7504,8 @@ static void vmx_recover_nmi_blocking(struct vcpu_vmx = *vmx) static void __vmx_complete_interrupts(struct kvm_vcpu *vcpu, u32 idt_vectoring_info, int instr_len_field, - int error_code_field) + int error_code_field, + int event_data_field) { u8 vector; int type; @@ -7500,14 +7540,18 @@ static void __vmx_complete_interrupts(struct kvm_vc= pu *vcpu, fallthrough; case INTR_TYPE_HARD_EXCEPTION: { u32 error_code =3D 0; + u64 event_data =3D 0; =20 if (idt_vectoring_info & VECTORING_INFO_DELIVER_CODE_MASK) error_code =3D vmcs_read32(error_code_field); + if (is_fred_enabled(vcpu)) + event_data =3D vmcs_read64(event_data_field); =20 kvm_requeue_exception(vcpu, vector, idt_vectoring_info & VECTORING_INFO_DELIVER_CODE_MASK, error_code, - idt_vectoring_info & VECTORING_INFO_NESTED_EXCEPTION_MASK); + idt_vectoring_info & VECTORING_INFO_NESTED_EXCEPTION_MASK, + event_data); break; } case INTR_TYPE_SOFT_INTR: @@ -7525,7 +7569,8 @@ static void vmx_complete_interrupts(struct vcpu_vmx *= vmx) { __vmx_complete_interrupts(&vmx->vcpu, vmx->idt_vectoring_info, VM_EXIT_INSTRUCTION_LEN, - IDT_VECTORING_ERROR_CODE); + IDT_VECTORING_ERROR_CODE, + ORIGINAL_EVENT_DATA); } =20 void vmx_cancel_injection(struct kvm_vcpu *vcpu) @@ -7533,7 +7578,8 @@ void vmx_cancel_injection(struct kvm_vcpu *vcpu) __vmx_complete_interrupts(vcpu, vmcs_read32(VM_ENTRY_INTR_INFO_FIELD), VM_ENTRY_INSTRUCTION_LEN, - VM_ENTRY_EXCEPTION_ERROR_CODE); + VM_ENTRY_EXCEPTION_ERROR_CODE, + INJECTED_EVENT_DATA); =20 vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0); } @@ -7645,6 +7691,10 @@ static noinstr void vmx_vcpu_enter_exit(struct kvm_v= cpu *vcpu, =20 vmx_disable_fb_clear(vmx); =20 + /* + * Note, even though FRED delivers the faulting linear address via the + * event data field on the stack, CR2 is still updated. + */ if (vcpu->arch.cr2 !=3D native_read_cr2()) native_write_cr2(vcpu->arch.cr2); =20 diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 94d684210cf6..e10ac6b280f6 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -431,9 +431,22 @@ void kvm_deliver_exception_payload(struct kvm_vcpu *vc= pu, * breakpoint), it is reserved and must be zero in DR6. */ vcpu->arch.dr6 &=3D ~BIT(12); + + /* + * FRED #DB event data matches DR6, but follows the polarity of + * VMX's pending debug exceptions, not DR6. + */ + ex->event_data =3D ex->payload & ~BIT(12); + break; + case NM_VECTOR: + ex->event_data =3D ex->payload; break; case PF_VECTOR: vcpu->arch.cr2 =3D ex->payload; + ex->event_data =3D ex->payload; + break; + default: + ex->event_data =3D 0; break; } =20 @@ -493,6 +506,10 @@ static void kvm_multiple_exception(struct kvm_vcpu *vc= pu, unsigned int nr, (is_nested || vcpu->arch.nmi_injected || vcpu->arch.interrupt.injected); + /* + * Do not update the event data, as the current value may have + * just been restored during a VM save/restore or live migration. + */ return; } =20 @@ -548,7 +565,7 @@ static void kvm_queue_exception_e_p(struct kvm_vcpu *vc= pu, unsigned nr, =20 void kvm_requeue_exception(struct kvm_vcpu *vcpu, unsigned int nr, bool has_error_code, u32 error_code, - bool is_nested) + bool is_nested, u64 event_data) { =20 /* @@ -574,6 +591,7 @@ void kvm_requeue_exception(struct kvm_vcpu *vcpu, unsig= ned int nr, vcpu->arch.exception.has_payload =3D false; vcpu->arch.exception.payload =3D 0; vcpu->arch.exception.is_nested =3D is_nested; + vcpu->arch.exception.event_data =3D event_data; } EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_requeue_exception); =20 @@ -3012,6 +3030,7 @@ static void kvm_vcpu_ioctl_x86_get_vcpu_events(struct= kvm_vcpu *vcpu, events->exception_has_payload =3D ex->has_payload; events->exception_payload =3D ex->payload; events->exception_is_nested =3D ex->is_nested; + events->exception_event_data =3D ex->event_data; =20 events->interrupt.injected =3D vcpu->arch.interrupt.injected && !vcpu->arch.interrupt.soft; @@ -3074,6 +3093,7 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct = kvm_vcpu *vcpu, return -EINVAL; } else { events->exception_is_nested =3D 0; + events->exception_event_data =3D 0; } =20 if ((events->exception.injected || events->exception.pending) && @@ -3102,6 +3122,7 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct = kvm_vcpu *vcpu, vcpu->arch.exception.has_payload =3D events->exception_has_payload; vcpu->arch.exception.payload =3D events->exception_payload; vcpu->arch.exception.is_nested =3D events->exception_is_nested; + vcpu->arch.exception.event_data =3D events->exception_event_data; =20 vcpu->arch.interrupt.injected =3D events->interrupt.injected; vcpu->arch.interrupt.nr =3D events->interrupt.nr; diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index 2d6bae66cfae..43c5c08f5d5c 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -159,6 +159,7 @@ static inline void kvm_clear_exception_queue(struct kvm= _vcpu *vcpu) vcpu->arch.exception.pending =3D false; vcpu->arch.exception.injected =3D false; vcpu->arch.exception.is_nested =3D false; + vcpu->arch.exception.event_data =3D 0; vcpu->arch.exception_vmexit.pending =3D false; } =20 @@ -504,7 +505,7 @@ void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsig= ned nr, u32 error_code); void kvm_queue_exception_p(struct kvm_vcpu *vcpu, unsigned nr, unsigned lo= ng payload); void kvm_requeue_exception(struct kvm_vcpu *vcpu, unsigned int nr, bool has_error_code, u32 error_code, - bool is_nested); + bool is_nested, u64 event_data); void kvm_inject_page_fault(struct kvm_vcpu *vcpu, struct x86_exception *fa= ult, bool from_hardware); void __kvm_inject_emulated_page_fault(struct kvm_vcpu *vcpu, --=20 2.43.0 From nobody Fri Sep 25 13:16:55 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) (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 2E9174A4983; Fri, 11 Sep 2026 21:42:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162933; cv=none; b=r78s3uSQeg0jzvLzSm3ytJtw5wH7JCxPF+w5+fuuDOKYnVrtp7QGoba5k0JKIB8r42NgQLgvpPyBF5SgTIgqRh1fDts+F1IT4iYNa8rDEgBUNchFJ3wxPRuphfh8lyL1zlHEfIInNP7KXlJMstkLTdh0RgQ5Ozf8v7IOlOOCrxc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162933; c=relaxed/simple; bh=uME2D72vWU1Qt9DlOEkO5iOKA32h3uQ2jXteCliDKSY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Z3SyjZtPMkJgHHFRi1s33UZDl88EnsFh7QZrEa1aguHSR2X0cq25F2k52a2oBtarBdpBI15zFcSfOHfvwGWSVaNjsvWAZH2a4QVh7OYEnDTksHHB326a1Et3p3GYXNt/3SUmsdD9Ka3kGAJL3ppt7gbx0bmuYTiuD1I9HbJ7DJA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=Pc+jKPkD; arc=none smtp.client-ip=192.198.163.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="Pc+jKPkD" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789162931; x=1820698931; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=uME2D72vWU1Qt9DlOEkO5iOKA32h3uQ2jXteCliDKSY=; b=Pc+jKPkDJ9XbCWT9JAUhBnBrF5osOMsqYV7ZjE8qq/N3YtdmZIoDzVTt zUnrVWHjVuvDiZB6GVGJNwUx6VPrwvwJbzaMXC/heDNZg457gUnuM530h 0gQzG3WN+fEV8wg6Ao3F9Z/3Uy1G95rXoavH0pieT3N3I1bk0uBXf2YTj MIBzHyNyaDN5/m8t1LF1G+NSC0se0GlpPjHBoHJ5hYW8LzjYtM2EZng3N 3Q3+egP69Rk++cyf3/LJAf1tG2qtVBfpm7CRH1uo04+HjO29s+nL4kgRX rzdvVD9iS/AUxOz9Iozvwatabx0Xq7NhUoPpjl7ZcffJ4DFkc8xdX3M1n Q==; X-CSE-ConnectionGUID: DlAlWB/MTbOw0Q2Fz6XVZw== X-CSE-MsgGUID: a27rVBCCRSKd9utpekRBEw== X-IronPort-AV: E=McAfee;i="6800,10657,11902"; a="88572720" X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="88572720" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Sep 2026 14:42:10 -0700 X-CSE-ConnectionGUID: PJcsdByjTx+GtKnOVUe8TQ== X-CSE-MsgGUID: TuzcDgpYTIK4bm2tzHG+1Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="272004162" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa007.jf.intel.com with ESMTP; 11 Sep 2026 14:42:09 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Paolo Bonzini , Sean Christopherson , Jonathan Corbet , Shuah Khan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Xin Li , Andy Lutomirski , Peter Zijlstra , Andrew Cooper , Tom Lendacky , Nikunj A Dadhania , Shivansh Dhiman , David Woodhouse , Chao Gao , Binbin Wu , Sohil Mehta , Zhao Liu , Yosry Ahmed , David Matlack , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v10 15/28] KVM: x86: Include CR4.FRED in the emulator CR4 write mask Date: Fri, 11 Sep 2026 14:36:45 -0700 Message-ID: <20260911213659.2025974-16-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260911213659.2025974-1-sohil.mehta@intel.com> References: <20260911213659.2025974-1-sohil.mehta@intel.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 Add CR4.FRED to the emulator's CR4 write mask. Historically, CR4 was restricted to its lower 32 bits in the x86 architecture. With the introduction of FRED, CR4 is expanded to use its higher 32 bits to accommodate the FRED enablement bit at position 32. Update the mask to ensure the emulator correctly handles FRED initialization and prevents the inadvertent truncation of high-order bits. Signed-off-by: Xin Li Signed-off-by: Sohil Mehta --- v10: - New patch --- arch/x86/kvm/regs.h | 2 +- arch/x86/kvm/x86.c | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/regs.h b/arch/x86/kvm/regs.h index 4e641a6c20f9..ef46918daf43 100644 --- a/arch/x86/kvm/regs.h +++ b/arch/x86/kvm/regs.h @@ -8,7 +8,7 @@ #define KVM_POSSIBLE_CR4_GUEST_BITS \ (X86_CR4_PVI | X86_CR4_DE | X86_CR4_PCE | X86_CR4_OSFXSR \ | X86_CR4_OSXMMEXCPT | X86_CR4_PGE | X86_CR4_TSD | X86_CR4_FSGSBASE \ - | X86_CR4_CET) + | X86_CR4_CET | X86_CR4_FRED) =20 #define X86_CR0_PDPTR_BITS (X86_CR0_CD | X86_CR0_NW | X86_CR0_PG) #define X86_CR4_TLBFLUSH_BITS (X86_CR4_PGE | X86_CR4_PCIDE | X86_CR4_PAE |= X86_CR4_SMEP) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index e10ac6b280f6..f264bc9c35f9 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -5552,11 +5552,17 @@ static int emulator_set_dr(struct x86_emulate_ctxt = *ctxt, int dr, return kvm_set_dr(emul_to_vcpu(ctxt), dr, value); } =20 -static u64 mk_cr_64(u64 curr_cr, u32 new_val) +static u64 mk_cr0_64(u64 curr_cr, u32 new_val) { return (curr_cr & ~((1ULL << 32) - 1)) | new_val; } =20 +static u64 mk_cr4_64(struct kvm_vcpu *vcpu, u64 curr_cr, u64 new_val) +{ + u32 shift =3D guest_cpu_cap_has(vcpu, X86_FEATURE_FRED) ? 33 : 32; + return (curr_cr & ~((1ULL << shift) - 1)) | new_val; +} + static unsigned long emulator_get_cr(struct x86_emulate_ctxt *ctxt, int cr) { struct kvm_vcpu *vcpu =3D emul_to_vcpu(ctxt); @@ -5593,7 +5599,7 @@ static int emulator_set_cr(struct x86_emulate_ctxt *c= txt, int cr, ulong val) =20 switch (cr) { case 0: - res =3D kvm_set_cr0(vcpu, mk_cr_64(kvm_read_cr0(vcpu), val)); + res =3D kvm_set_cr0(vcpu, mk_cr0_64(kvm_read_cr0(vcpu), val)); break; case 2: vcpu->arch.cr2 =3D val; @@ -5602,7 +5608,7 @@ static int emulator_set_cr(struct x86_emulate_ctxt *c= txt, int cr, ulong val) res =3D kvm_set_cr3(vcpu, val); break; case 4: - res =3D kvm_set_cr4(vcpu, mk_cr_64(kvm_read_cr4(vcpu), val)); + res =3D kvm_set_cr4(vcpu, mk_cr4_64(vcpu, kvm_read_cr4(vcpu), val)); break; case 8: res =3D kvm_set_cr8(vcpu, val); --=20 2.43.0 From nobody Fri Sep 25 13:16:55 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) (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 2144F4A4EE6; Fri, 11 Sep 2026 21:42:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162943; cv=none; b=uvMcJ6bFU9YginvHXLD9MrVzYTlTtv3Cjl28mrnloR8+8RQEDNlespvaCbEcIGl4/BAOvwAxoo1cMkAqRyUvOQN08OZ7gGPkJ/LBegwktw9AKxem+nYKROWfo8WaLjJJN0o3UvTattZylScJbeH/yK01AYQK0UD0YhUjxjZ7jxM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162943; c=relaxed/simple; bh=JX9TQ96K33ocxG2yk/VpQX5o1ho8/YkNayFOx7XyMt0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ysqpo1mxOguQ8HhcfcSjHudYnDivl7QRpBnxU0dpLsJLCVCROULr/rmDbm6s7rQZys4lcVS/kO2DfcciRI3dzzbzRJvRmzE+Ebfjm+tRlNxdyYLTeVpHyr3RtFHgaMQjT1l8vMALKAePmeENIolLo3qufWLeFsy60+oOKTI5cyQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=H3vFhdgt; arc=none smtp.client-ip=192.198.163.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="H3vFhdgt" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789162942; x=1820698942; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=JX9TQ96K33ocxG2yk/VpQX5o1ho8/YkNayFOx7XyMt0=; b=H3vFhdgtj3oh9XXHjlyfKLzqs1cuM18xlCg+OPrx0F4wJ3ctuvoJVRW8 a+jj0KJ/uFMvR8agewLw68NN4yTnIDMmr1cncMC5EyCgpHrBwf+1AbLNZ d0AKYA7rkXVdSEe3zk5XypuAs4lYb3+VqmOFbbyyRfre4eH0j1XAwYwsa 9ETh0I+ytlxUn1Refag5uLoumLfbbo8sMHLtyuqMzK9x1a93OBuBMSPW3 Pr/mHE2+oP6BFDQZtPKZuEx8gJxJ9BK68mDiYvuGemih62aS9GjnMmXJS 1emM+m/m252cW9Tb4h9r7oTJvj8uqGRB5AzO0WE6JAWnrwB/SMKTyAGAe g==; X-CSE-ConnectionGUID: h3BYHSXLSrCE4zF5qJbg3Q== X-CSE-MsgGUID: x7f0J7nuSeKxE+rHBJ0tKQ== X-IronPort-AV: E=McAfee;i="6800,10657,11902"; a="88572751" X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="88572751" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Sep 2026 14:42:22 -0700 X-CSE-ConnectionGUID: 1hjsGIMNSk+Fe5+exDuX8A== X-CSE-MsgGUID: j35rWwa9RpGbWIUPzK/5+w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="272004172" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa007.jf.intel.com with ESMTP; 11 Sep 2026 14:42:20 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Paolo Bonzini , Sean Christopherson , Jonathan Corbet , Shuah Khan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Xin Li , Andy Lutomirski , Peter Zijlstra , Andrew Cooper , Tom Lendacky , Nikunj A Dadhania , Shivansh Dhiman , David Woodhouse , Chao Gao , Binbin Wu , Sohil Mehta , Zhao Liu , Yosry Ahmed , David Matlack , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v10 16/28] KVM: x86: Mark CR4.FRED as not reserved Date: Fri, 11 Sep 2026 14:36:46 -0700 Message-ID: <20260911213659.2025974-17-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260911213659.2025974-1-sohil.mehta@intel.com> References: <20260911213659.2025974-1-sohil.mehta@intel.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 (Intel)" The CR4.FRED bit, i.e., CR4[32], is no longer a reserved bit when guest cpu cap has FRED, i.e., 1) All of FRED KVM support is in place. 2) Guest enumerates FRED. Otherwise it is still a reserved bit. Signed-off-by: Xin Li (Intel) Signed-off-by: Sohil Mehta --- v10: - Check CR4.FRED against IA-32e mode in kvm_set_cr4() instead of __kvm_is_valid_cr4(), so that KVM_SET_SREGS no longer rejects a CR4 and EFER pair that are loaded together (e.g., when restoring a FRED guest) --- arch/x86/kvm/regs.c | 7 +++++++ arch/x86/kvm/regs.h | 4 +++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/regs.c b/arch/x86/kvm/regs.c index 8f66438989e4..ba6c8856b4ff 100644 --- a/arch/x86/kvm/regs.c +++ b/arch/x86/kvm/regs.c @@ -429,6 +429,13 @@ int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long c= r4) return 1; } =20 + /* + * FRED can not be enabled when EFER.LMA=3D0. Note, MOV to CR4 outside + * 64-bit mode clears CR4[63:32] so only emulation can get here. + */ + if ((cr4 & X86_CR4_FRED) && !is_long_mode(vcpu)) + return 1; + if ((cr4 & X86_CR4_CET) && !kvm_is_cr0_bit_set(vcpu, X86_CR0_WP)) return 1; =20 diff --git a/arch/x86/kvm/regs.h b/arch/x86/kvm/regs.h index ef46918daf43..5db01693ad07 100644 --- a/arch/x86/kvm/regs.h +++ b/arch/x86/kvm/regs.h @@ -28,7 +28,7 @@ static_assert(!(KVM_POSSIBLE_CR0_GUEST_BITS & X86_CR0_PDP= TR_BITS)); | X86_CR4_OSXSAVE | X86_CR4_SMEP | X86_CR4_FSGSBASE \ | X86_CR4_OSXMMEXCPT | X86_CR4_LA57 | X86_CR4_VMXE \ | X86_CR4_SMAP | X86_CR4_PKE | X86_CR4_UMIP \ - | X86_CR4_LAM_SUP | X86_CR4_CET)) + | X86_CR4_LAM_SUP | X86_CR4_CET | X86_CR4_FRED)) =20 #define CR8_RESERVED_BITS (~(unsigned long)X86_CR8_TPR) =20 @@ -423,6 +423,8 @@ static inline bool __kvm_is_valid_cr4(struct kvm_vcpu *= vcpu, unsigned long cr4) if (!__cpu_has(__c, X86_FEATURE_SHSTK) && \ !__cpu_has(__c, X86_FEATURE_IBT)) \ __reserved_bits |=3D X86_CR4_CET; \ + if (!__cpu_has(__c, X86_FEATURE_FRED)) \ + __reserved_bits |=3D X86_CR4_FRED; \ __reserved_bits; \ }) =20 --=20 2.43.0 From nobody Fri Sep 25 13:16:55 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) (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 DFA54497B62; Fri, 11 Sep 2026 21:42:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162954; cv=none; b=tNcvM7Rl44XXWKHCaQlgrZTs/I5B4Lyb7/ptBCyRproZoZKdOFfbi2dHPcolScoWzZf+/tEnzGafJkLjf+FmB+SyI+h94sKm3oABq5YyRP7RoCXjDZdGbG+B+9sSezDHeSYd1MDls7+BqPiCOrpxjNK4UTTnCNn7rgmq10u8BdE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162954; c=relaxed/simple; bh=g9xfFIN1eybrlbdeBNPLXC5TVFM8Kvup/yimqq6mDiY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=kpjByyOnh0XRfa0SxTphKnOAJafMpGC6Mzlokusd7vsTt5Q1ZWqpE/AYPVgwxKvfHAONUm2j9kzWHGzv9zs0v7LFijM5zMhqK98pA1loieJYpfHqOn8BjRrh+r7Pd/lweHWWmdgd0nboapuSaeLkMldQyDg15DoY+4YG0StnPFo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=ZfqffOTl; arc=none smtp.client-ip=192.198.163.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="ZfqffOTl" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789162951; x=1820698951; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=g9xfFIN1eybrlbdeBNPLXC5TVFM8Kvup/yimqq6mDiY=; b=ZfqffOTlUxhn0j2kCulcfMstar/88d4h+yHPpX9vKTgAfDl+YrCgKtQR jyLJ1AEJahySKsJkgApija3ogvAmDBxYHEPOqJlCSGTCx2abnbvaFln5X uI/c/asrkwEWZ8y+Yj65teC04kHtRAS0RewDUiEP24MbfwjvdvKSvADxO Fiawzv1peI1AsP5j/JlKfpP+EXczf+mnUosnOV7mfPRCmhgtKapxKDB/X 0Uz7vFL2Nc/Zft+BB8tGc8lsstXeIjUFyFHkydIRu5605lIu74twN4Y7Y E72gXZuqdN1T8+bGQQepXdhpNdieXJoSBZ9nxdTtM0UL63mfOpx3NUN8i A==; X-CSE-ConnectionGUID: 8W4BmMHFQwKWgHPfItMKfw== X-CSE-MsgGUID: TsOAfeA5Tiym3g6Dcx+aHA== X-IronPort-AV: E=McAfee;i="6800,10657,11902"; a="88572765" X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="88572765" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Sep 2026 14:42:30 -0700 X-CSE-ConnectionGUID: 5H0pNPuTQ0m24jT5LNwtgw== X-CSE-MsgGUID: TycCSzVRQPWm6hxDCswdhg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="272004180" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa007.jf.intel.com with ESMTP; 11 Sep 2026 14:42:29 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Paolo Bonzini , Sean Christopherson , Jonathan Corbet , Shuah Khan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Xin Li , Andy Lutomirski , Peter Zijlstra , Andrew Cooper , Tom Lendacky , Nikunj A Dadhania , Shivansh Dhiman , David Woodhouse , Chao Gao , Binbin Wu , Sohil Mehta , Zhao Liu , Yosry Ahmed , David Matlack , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v10 17/28] KVM: x86: Handle CR4.FRED when emulating RSM Date: Fri, 11 Sep 2026 14:36:47 -0700 Message-ID: <20260911213659.2025974-18-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260911213659.2025974-1-sohil.mehta@intel.com> References: <20260911213659.2025974-1-sohil.mehta@intel.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" Clear CR4.FRED before CR0.PG when leaving long mode on RSM, and restore it only after CR0.PG has been set, the same way CR4.PCIDE is already handled in both directions. SMI delivery saves all 64 bits of CR4 and RSM restores them so CR4.FRED survives SMM. But KVM emulates RSM as a series of individual register writes, and so drives the vCPU through an intermediate state with CR4.FRED set and EFER.LMA clear. kvm_set_cr4() rejects that combination, so RSM of a 64-bit FRED guest fails with X86EMUL_UNHANDLEABLE. Note, SMI delivery needs no such handling, as enter_smm() clears CR4 in full via the vendor callback rather than kvm_set_cr4(). Signed-off-by: Sohil Mehta --- v10: - New patch --- arch/x86/kvm/smm.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/arch/x86/kvm/smm.c b/arch/x86/kvm/smm.c index 656a38dad7e7..a504e93fc5f5 100644 --- a/arch/x86/kvm/smm.c +++ b/arch/x86/kvm/smm.c @@ -435,10 +435,10 @@ static int rsm_enter_protected_mode(struct kvm_vcpu *= vcpu, =20 /* * First enable PAE, long mode needs it before CR0.PG =3D 1 is set. - * Then enable protected mode. However, PCID cannot be enabled - * if EFER.LMA=3D0, so set it separately. + * Then enable protected mode. However, PCID and FRED cannot be + * enabled if EFER.LMA=3D0, so set them separately. */ - bad =3D kvm_set_cr4(vcpu, cr4 & ~X86_CR4_PCIDE); + bad =3D kvm_set_cr4(vcpu, cr4 & ~(X86_CR4_PCIDE | X86_CR4_FRED)); if (bad) return X86EMUL_UNHANDLEABLE; =20 @@ -446,7 +446,7 @@ static int rsm_enter_protected_mode(struct kvm_vcpu *vc= pu, if (bad) return X86EMUL_UNHANDLEABLE; =20 - if (cr4 & X86_CR4_PCIDE) { + if (cr4 & (X86_CR4_PCIDE | X86_CR4_FRED)) { bad =3D kvm_set_cr4(vcpu, cr4); if (bad) return X86EMUL_UNHANDLEABLE; @@ -599,10 +599,14 @@ int emulator_leave_smm(struct x86_emulate_ctxt *ctxt) struct kvm_segment cs_desc; unsigned long cr4; =20 - /* Zero CR4.PCIDE before CR0.PG. */ + /* + * Zero CR4.PCIDE and CR4.FRED before CR0.PG, as neither can + * be set while EFER.LMA is 0, and clearing CR0.PG clears + * EFER.LMA. + */ cr4 =3D kvm_read_cr4(vcpu); - if (cr4 & X86_CR4_PCIDE) - kvm_set_cr4(vcpu, cr4 & ~X86_CR4_PCIDE); + if (cr4 & (X86_CR4_PCIDE | X86_CR4_FRED)) + kvm_set_cr4(vcpu, cr4 & ~(X86_CR4_PCIDE | X86_CR4_FRED)); =20 /* A 32-bit code segment is required to clear EFER.LMA. */ memset(&cs_desc, 0, sizeof(cs_desc)); --=20 2.43.0 From nobody Fri Sep 25 13:16:55 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) (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 E4F894A4EEF; Fri, 11 Sep 2026 21:42:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162962; cv=none; b=ZumEhhBGIuoP+9MButw0jT+bYZDPHBv6Ic0+41fvRo+eaML6KtGqbFvA0ORPV1MAmXZrn9q0tUp8rgoFsRItgYmkKQmnEeZgYq0biDLjSHhXnkAdxM4O+ULELCUt5NBaSdT6Q4jQEfhSb8dxI32y0LvT0XzYHu1O14xOrqMA9RA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162962; c=relaxed/simple; bh=3sP2mJ0al+FQWnF7v1VPsurp6m4st9PEmZ6qJPKe5j4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=eyAZKdmnl87JvLLJ57un9CyaHT1AkhMxoIbfv6ucpFhipbp8oUPKS/3yaBk1WGLzaCFbigIBH+k3Io7zbtBpzpMblO/4NDlvuh9SvT07whSrtVj6x9C1LteUhG2Uo41ZM1qVQ5S+RLCrTKzcs3DH29QN2k/Dfs47SnJhlJcLK9o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=EL2Ipan8; arc=none smtp.client-ip=192.198.163.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="EL2Ipan8" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789162960; x=1820698960; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=3sP2mJ0al+FQWnF7v1VPsurp6m4st9PEmZ6qJPKe5j4=; b=EL2Ipan8F58WRhROwV+29KPoZBuTTKfF7Bvticez+1jKpSCe2HRGpVJ4 hhRs5Y9ff9NiD295aqkr5rLjhNGXZe3i0OEDAP5TL/HWJHkJhv1eckEGt 1GIwTLW8NA821xYxi6ciIHen8tsjbaESjsUKXmRJBselatOFLgx5y82oi Xkp90dwICyZ6URr040i0bpTt1CCC9ECJ9xulBqJ3sDkCVpDi46k/ggjw3 nnGVd+EK8TpNwbRMeOo7QSWYupfLzqrG70lAWRlMicpCtPRsvKCWPSAFx 3SH4GZ5ULf1WOHwdyEb8liYCeeVx+H1OT9aomN32nQDYylabdze/wc6Vp A==; X-CSE-ConnectionGUID: u87Euv9HSDmMDKBqpDB1Vw== X-CSE-MsgGUID: vREBGFATSzatUyNH92gZoQ== X-IronPort-AV: E=McAfee;i="6800,10657,11902"; a="88572783" X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="88572783" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Sep 2026 14:42:39 -0700 X-CSE-ConnectionGUID: Dk6T9qCIT1uwJxJZnZK4ww== X-CSE-MsgGUID: 9aBkbqPdSGCwym1ORCPn2Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="272004193" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa007.jf.intel.com with ESMTP; 11 Sep 2026 14:42:38 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Paolo Bonzini , Sean Christopherson , Jonathan Corbet , Shuah Khan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Xin Li , Andy Lutomirski , Peter Zijlstra , Andrew Cooper , Tom Lendacky , Nikunj A Dadhania , Shivansh Dhiman , David Woodhouse , Chao Gao , Binbin Wu , Sohil Mehta , Zhao Liu , Yosry Ahmed , David Matlack , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v10 18/28] KVM: VMX: Dump FRED context in dump_vmcs() Date: Fri, 11 Sep 2026 14:36:48 -0700 Message-ID: <20260911213659.2025974-19-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260911213659.2025974-1-sohil.mehta@intel.com> References: <20260911213659.2025974-1-sohil.mehta@intel.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 (Intel)" Add FRED related VMCS fields to dump_vmcs() to dump FRED context. Signed-off-by: Xin Li (Intel) Signed-off-by: Sohil Mehta --- v10: - Test the secondary VM-exit controls in the dump_vmcs() --- arch/x86/kvm/vmx/vmx.c | 43 +++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index cd041381b322..3a3315a7fc11 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -1501,6 +1501,9 @@ static void vmx_write_guest_fred_rsp0(struct vcpu_vmx= *vmx, u64 data) vmx_write_guest_host_msr(vmx, MSR_IA32_FRED_RSP0, data, &vmx->msr_guest_fred_rsp0); } +#else +/* Make sure it builds on 32-bit */ +static u64 vmx_read_guest_fred_rsp0(struct vcpu_vmx *vmx) { return 0; } #endif =20 static void grow_ple_window(struct kvm_vcpu *vcpu) @@ -6727,7 +6730,7 @@ void dump_vmcs(struct kvm_vcpu *vcpu) struct vcpu_vmx *vmx =3D to_vmx(vcpu); u32 vmentry_ctl, vmexit_ctl; u32 cpu_based_exec_ctrl, pin_based_exec_ctrl, secondary_exec_control; - u64 tertiary_exec_control; + u64 tertiary_exec_control, secondary_vmexit_ctl; unsigned long cr4; int efer_slot; =20 @@ -6738,6 +6741,8 @@ void dump_vmcs(struct kvm_vcpu *vcpu) =20 vmentry_ctl =3D vmcs_read32(VM_ENTRY_CONTROLS); vmexit_ctl =3D vmcs_read32(VM_EXIT_CONTROLS); + secondary_vmexit_ctl =3D cpu_has_secondary_vmexit_ctrls() ? + vmcs_read64(SECONDARY_VM_EXIT_CONTROLS) : 0; cpu_based_exec_ctrl =3D vmcs_read32(CPU_BASED_VM_EXEC_CONTROL); pin_based_exec_ctrl =3D vmcs_read32(PIN_BASED_VM_EXEC_CONTROL); cr4 =3D vmcs_readl(GUEST_CR4); @@ -6784,6 +6789,16 @@ void dump_vmcs(struct kvm_vcpu *vcpu) vmx_dump_sel("LDTR:", GUEST_LDTR_SELECTOR); vmx_dump_dtsel("IDTR:", GUEST_IDTR_LIMIT); vmx_dump_sel("TR: ", GUEST_TR_SELECTOR); + if (vmentry_ctl & VM_ENTRY_LOAD_IA32_FRED) + pr_err("FRED guest: config=3D0x%016llx, stack_levels=3D0x%016llx\n" + "RSP0=3D0x%016llx, RSP1=3D0x%016llx\n" + "RSP2=3D0x%016llx, RSP3=3D0x%016llx\n", + vmcs_read64(GUEST_IA32_FRED_CONFIG), + vmcs_read64(GUEST_IA32_FRED_STKLVLS), + vmx_read_guest_fred_rsp0(vmx), + vmcs_read64(GUEST_IA32_FRED_RSP1), + vmcs_read64(GUEST_IA32_FRED_RSP2), + vmcs_read64(GUEST_IA32_FRED_RSP3)); efer_slot =3D vmx_find_loadstore_msr_slot(&vmx->msr_autoload.guest, MSR_E= FER); if (vmentry_ctl & VM_ENTRY_LOAD_IA32_EFER) pr_err("EFER=3D 0x%016llx\n", vmcs_read64(GUEST_IA32_EFER)); @@ -6835,6 +6850,16 @@ void dump_vmcs(struct kvm_vcpu *vcpu) vmcs_readl(HOST_TR_BASE)); pr_err("GDTBase=3D%016lx IDTBase=3D%016lx\n", vmcs_readl(HOST_GDTR_BASE), vmcs_readl(HOST_IDTR_BASE)); + if (secondary_vmexit_ctl & SECONDARY_VM_EXIT_LOAD_IA32_FRED) + pr_err("FRED host: config=3D0x%016llx, stack_levels=3D0x%016llx\n" + "RSP0=3D0x%016lx, RSP1=3D0x%016llx\n" + "RSP2=3D0x%016llx, RSP3=3D0x%016llx\n", + vmcs_read64(HOST_IA32_FRED_CONFIG), + vmcs_read64(HOST_IA32_FRED_STKLVLS), + (unsigned long)task_stack_page(current) + THREAD_SIZE, + vmcs_read64(HOST_IA32_FRED_RSP1), + vmcs_read64(HOST_IA32_FRED_RSP2), + vmcs_read64(HOST_IA32_FRED_RSP3)); pr_err("CR0=3D%016lx CR3=3D%016lx CR4=3D%016lx\n", vmcs_readl(HOST_CR0), vmcs_readl(HOST_CR3), vmcs_readl(HOST_CR4)); @@ -6860,25 +6885,29 @@ void dump_vmcs(struct kvm_vcpu *vcpu) pr_err("*** Control State ***\n"); pr_err("CPUBased=3D0x%08x SecondaryExec=3D0x%08x TertiaryExec=3D0x%016llx= \n", cpu_based_exec_ctrl, secondary_exec_control, tertiary_exec_control= ); - pr_err("PinBased=3D0x%08x EntryControls=3D%08x ExitControls=3D%08x\n", - pin_based_exec_ctrl, vmentry_ctl, vmexit_ctl); + pr_err("PinBased=3D0x%08x EntryControls=3D0x%08x\n", + pin_based_exec_ctrl, vmentry_ctl); + pr_err("ExitControls=3D0x%08x SecondaryExitControls=3D0x%016llx\n", + vmexit_ctl, secondary_vmexit_ctl); pr_err("ExceptionBitmap=3D%08x PFECmask=3D%08x PFECmatch=3D%08x\n", vmcs_read32(EXCEPTION_BITMAP), vmcs_read32(PAGE_FAULT_ERROR_CODE_MASK), vmcs_read32(PAGE_FAULT_ERROR_CODE_MATCH)); - pr_err("VMEntry: intr_info=3D%08x errcode=3D%08x ilen=3D%08x\n", + pr_err("VMEntry: intr_info=3D%08x errcode=3D%08x ilen=3D%08x event_data= =3D%016llx\n", vmcs_read32(VM_ENTRY_INTR_INFO_FIELD), vmcs_read32(VM_ENTRY_EXCEPTION_ERROR_CODE), - vmcs_read32(VM_ENTRY_INSTRUCTION_LEN)); + vmcs_read32(VM_ENTRY_INSTRUCTION_LEN), + kvm_cpu_cap_has(X86_FEATURE_FRED) ? vmcs_read64(INJECTED_EVENT_DAT= A) : 0); pr_err("VMExit: intr_info=3D%08x errcode=3D%08x ilen=3D%08x\n", vmcs_read32(VM_EXIT_INTR_INFO), vmcs_read32(VM_EXIT_INTR_ERROR_CODE), vmcs_read32(VM_EXIT_INSTRUCTION_LEN)); pr_err(" reason=3D%08x qualification=3D%016lx\n", vmcs_read32(VM_EXIT_REASON), vmcs_readl(EXIT_QUALIFICATION)); - pr_err("IDTVectoring: info=3D%08x errcode=3D%08x\n", + pr_err("IDTVectoring: info=3D%08x errcode=3D%08x event_data=3D%016llx\n", vmcs_read32(IDT_VECTORING_INFO_FIELD), - vmcs_read32(IDT_VECTORING_ERROR_CODE)); + vmcs_read32(IDT_VECTORING_ERROR_CODE), + kvm_cpu_cap_has(X86_FEATURE_FRED) ? vmcs_read64(ORIGINAL_EVENT_DAT= A) : 0); pr_err("TSC Offset =3D 0x%016llx\n", vmcs_read64(TSC_OFFSET)); if (secondary_exec_control & SECONDARY_EXEC_TSC_SCALING) pr_err("TSC Multiplier =3D 0x%016llx\n", --=20 2.43.0 From nobody Fri Sep 25 13:16:55 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) (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 F31064C4F47; Fri, 11 Sep 2026 21:42:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162969; cv=none; b=XQxcvan92I/1sL3bTYr5WECd4+x7BpcwpyiLhwuvQG7vA3dpeNYB0SRzc0tfePMR8yh9G4lQh5BVvNT7ewEXjhonJ4TxRFA8sl0kIUDQXiF9k5zxV1saXIRhB3xKxNhS3/X5UI7Xo/HRh4/FwzW1cPOtYpiVnFfmWmAdqyGsow0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162969; c=relaxed/simple; bh=BRECzFPPA04jMAm7WoR+5OiKCg4q6yf1+9bP69Dv8S0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tbSHgkMwoGI+8RPsMhEXipK10irz2UkAdMV1Efta1bqGgBH7Jkdh43p93XiHA2et4MqCz0/C1jMvkycYJfTyk4fZMstylwZKDZXSf2CAnfZLjmeF00zQOkGGAGyTCEcOUukoZjlY6tQQJho0XCwQqs2ZJ1fBpzab/62kCY+jlAQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=b6GopY7K; arc=none smtp.client-ip=192.198.163.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="b6GopY7K" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789162968; x=1820698968; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=BRECzFPPA04jMAm7WoR+5OiKCg4q6yf1+9bP69Dv8S0=; b=b6GopY7KZg9clBfYIYy50+81s1Q/28z/5C/1tMbiqHN3/p3XbRIJZJo2 eB8eMBA/2qVhXLLL3qmIEp3gUAf7CDFpPusd33U3q5uhAI0jq/1xBvxFP oSHkd/0jXiSpmNYDnhZMM+4Hf+oM7KCnlCmy+YaXgm6vSszL3ukYH8doZ 9z5Ug1QfMviWW3qiYPXenI53p1kuumCwdwQXxpJg41CU65q90vNfA3/23 ylbVnouDtQ2LfQ1NcJ/xDWzrdajo5fwDEnogOIigvwFhyzFnmhcm1KhwS ULoVAmeaKKFJiCDsI21Nq3qRcxfurnbJ8rjkmQOeRde3NEK74nhhJxXYO w==; X-CSE-ConnectionGUID: CFd9Nll+T9yLW8XeNkIFKw== X-CSE-MsgGUID: 6dzU6dcUTAWExcVq6F1JtA== X-IronPort-AV: E=McAfee;i="6800,10657,11902"; a="88572798" X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="88572798" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Sep 2026 14:42:47 -0700 X-CSE-ConnectionGUID: WtVZvhDGSfmpm4h+wgPt8g== X-CSE-MsgGUID: KUt5WrARQJu/ryBALRO0Qg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="272004213" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa007.jf.intel.com with ESMTP; 11 Sep 2026 14:42:46 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Paolo Bonzini , Sean Christopherson , Jonathan Corbet , Shuah Khan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Xin Li , Andy Lutomirski , Peter Zijlstra , Andrew Cooper , Tom Lendacky , Nikunj A Dadhania , Shivansh Dhiman , David Woodhouse , Chao Gao , Binbin Wu , Sohil Mehta , Zhao Liu , Yosry Ahmed , David Matlack , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v10 19/28] KVM: x86: Advertise support for FRED Date: Fri, 11 Sep 2026 14:36:49 -0700 Message-ID: <20260911213659.2025974-20-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260911213659.2025974-1-sohil.mehta@intel.com> References: <20260911213659.2025974-1-sohil.mehta@intel.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 (Intel)" Advertise support for FRED to userspace after changes required to enable FRED in a KVM guest are in place. Signed-off-by: Xin Li (Intel) Signed-off-by: Sohil Mehta Reviewed-by: Chao Gao --- v10: - kvm_cpu_cap_clear(X86_FEATURE_FRED) in svm_set_cpu_caps() (Chao). --- arch/x86/kvm/cpuid.c | 1 + arch/x86/kvm/svm/svm.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index ddb022cb203a..5682bacdfd32 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -1034,6 +1034,7 @@ void kvm_initialize_cpu_caps(void) F(FSRS), F(FSRC), F(WRMSRNS), + X86_64_F(FRED), X86_64_F(LKGS), F(AMX_FP16), F(AVX_IFMA), diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index f254a5ff570d..dd19c7b4e904 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -5518,6 +5518,9 @@ static __init void svm_set_cpu_caps(void) =20 kvm_cpu_cap_clear(X86_FEATURE_IBT); =20 + /* SVM FRED virtualization not implemented yet */ + kvm_cpu_cap_clear(X86_FEATURE_FRED); + /* CPUID 0x80000001 and 0x8000000A (SVM features) */ if (nested) { kvm_cpu_cap_set(X86_FEATURE_SVM); --=20 2.43.0 From nobody Fri Sep 25 13:16:55 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) (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 27C3E4CC632; Fri, 11 Sep 2026 21:42:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162980; cv=none; b=j1rdCViECImjelFqGGIUkhsWLtR/NTlkp0TGs/XLQC+a8XqHMZKdHC6bQ2nJIP7uzNdgIVdVkwXLNnv+3soq+FyfGyn9NWjNfCkGQmtMHnJ1FkkdeTfaNDTsjq769L1wVovRoA39OSq3W+DwFM89GnpI+/2kj78wYGPj5Iz0Zi0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162980; c=relaxed/simple; bh=STdr0QsW6MK5iHNJx3NyfDEnkdQFYbtOgLt5RoCUHiQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=maksI+rHeUF97gT4iyqZnqrtI4ERK1lPidhRxdCjerPZxtLzKmKj9Mi3y2uMWAYIQqmAmNOdhOLkrUwP2SoXkbeaV5VCuZesUShe6nPwCU1k0T02CyEyZAM4WPsAVUg9XKsxPXJzw5cJjPOwqVMHXAtMgFCxP87z+aQw7EifWKo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=KOy5h2nn; arc=none smtp.client-ip=192.198.163.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="KOy5h2nn" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789162978; x=1820698978; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=STdr0QsW6MK5iHNJx3NyfDEnkdQFYbtOgLt5RoCUHiQ=; b=KOy5h2nnzaxGEc+S2G5SI+/lgprcXMvhZtJZMXhgKBJaSz6MC10N8gBA UCt8tfxhiA7juq8yvWTj3swYhSqY+CaSOcJlpUmtPAhzUsod/Gtni9hLF oFpYpeQpuvDxKj/iLOUvSFE4ICYHziXRgc5HbRnfChKrZv593AoScaZGR Ho+TmttUle1dj8DZ7QYxlWuB3kUL8lrxTcSj5H1wsyORkHXyRKaIXkDUK k+NR7PM3+MxCna4bWBJwDYOHXWU/TTHIp4dQVKudkofBIH3Ls3RnDHTtR 3g3xPXJucxFuYHF5Dikem0cwcXLP31mnWsUPUOtUHUKN/TH8HjfCMdF74 w==; X-CSE-ConnectionGUID: p8N9+brJTHGAY7i3o42nZw== X-CSE-MsgGUID: XLCGEhbYTRyNyc7b17QvxA== X-IronPort-AV: E=McAfee;i="6800,10657,11902"; a="88572827" X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="88572827" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Sep 2026 14:42:57 -0700 X-CSE-ConnectionGUID: 8n2f3RnnRraSKwGQIzpeGA== X-CSE-MsgGUID: zcWRFngiQXuJ5mfMOPj64Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="272004230" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa007.jf.intel.com with ESMTP; 11 Sep 2026 14:42:56 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Paolo Bonzini , Sean Christopherson , Jonathan Corbet , Shuah Khan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Xin Li , Andy Lutomirski , Peter Zijlstra , Andrew Cooper , Tom Lendacky , Nikunj A Dadhania , Shivansh Dhiman , David Woodhouse , Chao Gao , Binbin Wu , Sohil Mehta , Zhao Liu , Yosry Ahmed , David Matlack , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v10 20/28] KVM: nVMX: Enable support for secondary VM exit controls Date: Fri, 11 Sep 2026 14:36:50 -0700 Message-ID: <20260911213659.2025974-21-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260911213659.2025974-1-sohil.mehta@intel.com> References: <20260911213659.2025974-1-sohil.mehta@intel.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 (Intel)" Add support for secondary VM exit controls in nested VMX to facilitate future FRED integration. Signed-off-by: Xin Li (Intel) Signed-off-by: Sohil Mehta --- v10: - Add MSR_IA32_VMX_EXIT_CTLS2 to emulated_msrs_all[] for live migration. (Chao Gao) - Reject vmcs12's secondary VM exit controls that KVM doesn't advertise to L1 in MSR_IA32_VMX_EXIT_CTLS2. --- arch/x86/kvm/msrs.c | 1 + arch/x86/kvm/msrs.h | 2 +- arch/x86/kvm/vmx/capabilities.h | 1 + arch/x86/kvm/vmx/nested.c | 29 ++++++++++++++++++++++++++++- arch/x86/kvm/vmx/nested.h | 5 +++++ arch/x86/kvm/vmx/vmcs12.c | 1 + arch/x86/kvm/vmx/vmcs12.h | 3 ++- 7 files changed, 39 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/msrs.c b/arch/x86/kvm/msrs.c index 9eabb7b02cb5..3260bddb5f52 100644 --- a/arch/x86/kvm/msrs.c +++ b/arch/x86/kvm/msrs.c @@ -317,6 +317,7 @@ static const u32 emulated_msrs_all[] =3D { MSR_IA32_VMX_PROCBASED_CTLS2, MSR_IA32_VMX_EPT_VPID_CAP, MSR_IA32_VMX_VMFUNC, + MSR_IA32_VMX_EXIT_CTLS2, =20 MSR_K7_HWCR, MSR_KVM_POLL_CONTROL, diff --git a/arch/x86/kvm/msrs.h b/arch/x86/kvm/msrs.h index 7cc182a15b3b..845d2cbe80e5 100644 --- a/arch/x86/kvm/msrs.h +++ b/arch/x86/kvm/msrs.h @@ -31,7 +31,7 @@ static inline void kvm_pr_unimpl_rdmsr(struct kvm_vcpu *v= cpu, u32 msr) * associated feature that KVM supports for nested virtualization. */ #define KVM_FIRST_EMULATED_VMX_MSR MSR_IA32_VMX_BASIC -#define KVM_LAST_EMULATED_VMX_MSR MSR_IA32_VMX_VMFUNC +#define KVM_LAST_EMULATED_VMX_MSR MSR_IA32_VMX_EXIT_CTLS2 =20 /* * KVM's internal, non-ABI indices for synthetic MSRs. The values themselv= es diff --git a/arch/x86/kvm/vmx/capabilities.h b/arch/x86/kvm/vmx/capabilitie= s.h index 95d22a54f856..9cca65b226fd 100644 --- a/arch/x86/kvm/vmx/capabilities.h +++ b/arch/x86/kvm/vmx/capabilities.h @@ -36,6 +36,7 @@ struct nested_vmx_msrs { u32 pinbased_ctls_high; u32 exit_ctls_low; u32 exit_ctls_high; + u64 secondary_exit_ctls; u32 entry_ctls_low; u32 entry_ctls_high; u32 misc_low; diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 151873407abd..6576935b9d43 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -1596,6 +1596,11 @@ int vmx_set_vmx_msr(struct kvm_vcpu *vcpu, u32 msr_i= ndex, u64 data) return -EINVAL; vmx->nested.msrs.vmfunc_controls =3D data; return 0; + case MSR_IA32_VMX_EXIT_CTLS2: + if (data & ~vmcs_config.nested.secondary_exit_ctls) + return -EINVAL; + vmx->nested.msrs.secondary_exit_ctls =3D data; + return 0; default: /* * The rest of the VMX capability MSRs do not support restore. @@ -1635,6 +1640,9 @@ int vmx_get_vmx_msr(struct nested_vmx_msrs *msrs, u32= msr_index, u64 *pdata) if (msr_index =3D=3D MSR_IA32_VMX_EXIT_CTLS) *pdata |=3D VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR; break; + case MSR_IA32_VMX_EXIT_CTLS2: + *pdata =3D msrs->secondary_exit_ctls; + break; case MSR_IA32_VMX_TRUE_ENTRY_CTLS: case MSR_IA32_VMX_ENTRY_CTLS: *pdata =3D vmx_control_msr( @@ -2576,6 +2584,9 @@ static void prepare_vmcs02_early(struct vcpu_vmx *vmx= , struct loaded_vmcs *vmcs0 exec_control &=3D ~VM_EXIT_LOAD_IA32_EFER; vm_exit_controls_set(vmx, exec_control); =20 + if (exec_control & VM_EXIT_ACTIVATE_SECONDARY_CONTROLS) + secondary_vm_exit_controls_set(vmx, __secondary_vm_exit_controls_get(vmc= s01)); + /* * Interrupt/Exception Fields */ @@ -3040,6 +3051,11 @@ static int nested_check_vm_exit_controls(struct kvm_= vcpu *vcpu, CC(nested_vmx_check_exit_msr_switch_controls(vcpu, vmcs12))) return -EINVAL; =20 + if (nested_cpu_has_secondary_vm_exit_controls(vmcs12) && + CC(vmcs12->secondary_vm_exit_controls & + ~vmx->nested.msrs.secondary_exit_ctls)) + return -EINVAL; + return 0; } =20 @@ -7152,7 +7168,8 @@ static void nested_vmx_setup_exit_ctls(struct vmcs_co= nfig *vmcs_conf, VM_EXIT_HOST_ADDR_SPACE_SIZE | #endif VM_EXIT_LOAD_IA32_PAT | VM_EXIT_SAVE_IA32_PAT | - VM_EXIT_CLEAR_BNDCFGS | VM_EXIT_LOAD_CET_STATE; + VM_EXIT_CLEAR_BNDCFGS | VM_EXIT_LOAD_CET_STATE | + VM_EXIT_ACTIVATE_SECONDARY_CONTROLS; msrs->exit_ctls_high |=3D VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR | VM_EXIT_LOAD_IA32_EFER | VM_EXIT_SAVE_IA32_EFER | @@ -7165,6 +7182,16 @@ static void nested_vmx_setup_exit_ctls(struct vmcs_c= onfig *vmcs_conf, =20 /* We support free control of debug control saving. */ msrs->exit_ctls_low &=3D ~VM_EXIT_SAVE_DEBUG_CONTROLS; + + if (msrs->exit_ctls_high & VM_EXIT_ACTIVATE_SECONDARY_CONTROLS) { + msrs->secondary_exit_ctls =3D vmcs_conf->vmexit_2nd_ctrl; + /* + * As the secondary VM exit control is always loaded, do not + * advertise any feature in it to nVMX until its nVMX support + * is ready. + */ + msrs->secondary_exit_ctls &=3D 0; + } } =20 static void nested_vmx_setup_entry_ctls(struct vmcs_config *vmcs_conf, diff --git a/arch/x86/kvm/vmx/nested.h b/arch/x86/kvm/vmx/nested.h index c6de848bd9ce..371fc3498b12 100644 --- a/arch/x86/kvm/vmx/nested.h +++ b/arch/x86/kvm/vmx/nested.h @@ -247,6 +247,11 @@ static inline bool nested_cpu_has_save_preemption_time= r(struct vmcs12 *vmcs12) VM_EXIT_SAVE_VMX_PREEMPTION_TIMER; } =20 +static inline bool nested_cpu_has_secondary_vm_exit_controls(struct vmcs12= *vmcs12) +{ + return vmcs12->vm_exit_controls & VM_EXIT_ACTIVATE_SECONDARY_CONTROLS; +} + static inline bool nested_exit_on_nmi(struct kvm_vcpu *vcpu) { return nested_cpu_has_nmi_exiting(get_vmcs12(vcpu)); diff --git a/arch/x86/kvm/vmx/vmcs12.c b/arch/x86/kvm/vmx/vmcs12.c index 1ebe67c384ad..9d64a89aff00 100644 --- a/arch/x86/kvm/vmx/vmcs12.c +++ b/arch/x86/kvm/vmx/vmcs12.c @@ -66,6 +66,7 @@ static const u16 kvm_supported_vmcs12_field_offsets[] __i= nitconst =3D { FIELD64(HOST_IA32_PAT, host_ia32_pat), FIELD64(HOST_IA32_EFER, host_ia32_efer), FIELD64(HOST_IA32_PERF_GLOBAL_CTRL, host_ia32_perf_global_ctrl), + FIELD64(SECONDARY_VM_EXIT_CONTROLS, secondary_vm_exit_controls), FIELD(PIN_BASED_VM_EXEC_CONTROL, pin_based_vm_exec_control), FIELD(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control), FIELD(EXCEPTION_BITMAP, exception_bitmap), diff --git a/arch/x86/kvm/vmx/vmcs12.h b/arch/x86/kvm/vmx/vmcs12.h index 21cd1b75e4fd..bb2f406be63d 100644 --- a/arch/x86/kvm/vmx/vmcs12.h +++ b/arch/x86/kvm/vmx/vmcs12.h @@ -71,7 +71,7 @@ struct __packed vmcs12 { u64 pml_address; u64 encls_exiting_bitmap; u64 tsc_multiplier; - u64 padding64[1]; /* room for future expansion */ + u64 secondary_vm_exit_controls; /* * To allow migration of L1 (complete with its L2 guests) between * machines of different natural widths (32 or 64 bit), we cannot have @@ -261,6 +261,7 @@ static inline void vmx_check_vmcs12_offsets(void) CHECK_OFFSET(pml_address, 312); CHECK_OFFSET(encls_exiting_bitmap, 320); CHECK_OFFSET(tsc_multiplier, 328); + CHECK_OFFSET(secondary_vm_exit_controls, 336); CHECK_OFFSET(cr0_guest_host_mask, 344); CHECK_OFFSET(cr4_guest_host_mask, 352); CHECK_OFFSET(cr0_read_shadow, 360); --=20 2.43.0 From nobody Fri Sep 25 13:16:55 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) (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 2D2424D09F4; Fri, 11 Sep 2026 21:43:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162991; cv=none; b=L9IKEG69qNs5IyeQSKdxpoTTJDcGmOq58vS4caOtSvndsIBxQeAFRFynfsP2EAwxHoDzB7qRO5T28Wdb2w0cv33F8GBE/A/GqStGFzr9vyOC8Ui4PVFkwRHcWhT/TKFqw0kYglg2wy/4NP5VTehyyvt27OXvDyX+n/xLI6sNXOE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789162991; c=relaxed/simple; bh=71Nyn+QFU6de0oC7XG8VEGVcvldUvlJUjtOuNukoA6w=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uLHqoBjkO3QZYupwox1cpA4S+cT1Mf8xWqcPRjWkxrWOh+feL6GOt6CWNw/A+d2XBh7Y8cARaFM++JsYuGig2KBzD+IZSRdehtWMKID+59Cl5FJkNXXetEs33KOQDpR6PqFeesDy7ODti/vCwXI7aD0FS0As1weZibEmgGSMsKg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=hgVrVZhn; arc=none smtp.client-ip=192.198.163.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="hgVrVZhn" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789162988; x=1820698988; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=71Nyn+QFU6de0oC7XG8VEGVcvldUvlJUjtOuNukoA6w=; b=hgVrVZhnyyduFDR6nVVtLWehWg98VAr8I6h7rBb9++jmS9BU0zuKWY8r T9x0q5ouLCsuyo2Cn7UzvhrSNbglGimiQy0uDf8k2ePdcaaJBD57C3LnJ KidcegtcUl2mUgeiM8xq4uEjycLNssGoI0Nd5E2quuRipgQgSnO32Lbju Epd5XlAphs5cjDLYIxImrgTHGwwp0WH1EAfbS58V6ow2fhrLHubjAwkT9 MpifDfxYKLW/RXgy9J/KcJepXhKiHuMkTen+tfUpmh2QjQKXIUprO815e NUj2ZI2dXAWxqnB1QVoHePJZxayYUebXwpN5Snx3eqpzx+hBW4ybaUx4j g==; X-CSE-ConnectionGUID: rFXqRsa/QdW67MQv495gVA== X-CSE-MsgGUID: RYY15F+qSqKdwy/Rdje/Sw== X-IronPort-AV: E=McAfee;i="6800,10657,11902"; a="88572845" X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="88572845" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Sep 2026 14:43:07 -0700 X-CSE-ConnectionGUID: c9zPwHakSkKyLxUkSI6ZhQ== X-CSE-MsgGUID: iJLCVNdhQ+214cc5otv54g== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="272004253" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa007.jf.intel.com with ESMTP; 11 Sep 2026 14:43:06 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Paolo Bonzini , Sean Christopherson , Jonathan Corbet , Shuah Khan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Xin Li , Andy Lutomirski , Peter Zijlstra , Andrew Cooper , Tom Lendacky , Nikunj A Dadhania , Shivansh Dhiman , David Woodhouse , Chao Gao , Binbin Wu , Sohil Mehta , Zhao Liu , Yosry Ahmed , David Matlack , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v10 21/28] KVM: nVMX: Handle FRED VMCS fields in nested VMX context Date: Fri, 11 Sep 2026 14:36:51 -0700 Message-ID: <20260911213659.2025974-22-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260911213659.2025974-1-sohil.mehta@intel.com> References: <20260911213659.2025974-1-sohil.mehta@intel.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 (Intel)" Extend nested VMX context management to include FRED-related VMCS fields, enabling proper handling of FRED state during nested virtualization. Because KVM always sets SECONDARY_VM_EXIT_SAVE_IA32_FRED, FRED MSRs are always saved to vmcs02. However an L1 VMM may choose to clear this bit, i.e., not to save FRED MSRs to vmcs12. This is not a problem when the L1 VMM sets SECONDARY_VM_EXIT_LOAD_IA32_FRED, as KVM then immediately loads host FRED MSRs of vmcs12 to guest FRED MSRs of vmcs01. However if the L1 VMM clears SECONDARY_VM_EXIT_LOAD_IA32_FRED, KVM should retain FRED MSRs to run the L1 VMM. To propagate guest FRED MSRs from vmcs02 to vmcs01, save them in sync_vmcs02_to_vmcs12() regardless of whether SECONDARY_VM_EXIT_SAVE_IA32_FRED is set in vmcs12. Then, use the saved values to set guest FRED MSRs in vmcs01 within load_vmcs12_host_state() when !nested_cpu_load_host_fred_state(). Signed-off-by: Xin Li (Intel) Signed-off-by: Sohil Mehta --- v10: - Simplify nested FRED MSRs update with read/write helpers (Chao). - Add other FRED MSRS to MSR bitmap nested filtering (Chao). - Add {ORIGINAL,INJECTED}_EVENT_DATA to shadow fields in a separate patch (Sean). - Add a new parameter to load_vmcs12_host_state() to indicate the call is from a failed VM entry. - Update exception status member variable nested to is_nested (Sean). v9: - Rebase to kvm-x86/next. - Guard FRED state save/restore with guest_cpu_cap_has(vcpu, X86_FEATURE_FRED) (syzbot & Chao). --- arch/x86/kvm/vmx/capabilities.h | 5 ++ arch/x86/kvm/vmx/nested.c | 107 ++++++++++++++++++++++++++++++-- arch/x86/kvm/vmx/nested.h | 17 +++++ arch/x86/kvm/vmx/vmcs.h | 11 ++++ arch/x86/kvm/vmx/vmcs12.c | 18 ++++++ arch/x86/kvm/vmx/vmcs12.h | 39 ++++++++++++ arch/x86/kvm/vmx/vmx.h | 23 +++++++ 7 files changed, 214 insertions(+), 6 deletions(-) diff --git a/arch/x86/kvm/vmx/capabilities.h b/arch/x86/kvm/vmx/capabilitie= s.h index 9cca65b226fd..74456f4533e9 100644 --- a/arch/x86/kvm/vmx/capabilities.h +++ b/arch/x86/kvm/vmx/capabilities.h @@ -82,6 +82,11 @@ static inline bool cpu_has_vmx_basic_no_hw_errcode_cc(vo= id) return vmcs_config.basic & VMX_BASIC_NO_HW_ERROR_CODE_CC; } =20 +static inline bool cpu_has_vmx_nested_exception(void) +{ + return vmcs_config.basic & VMX_BASIC_NESTED_EXCEPTION; +} + static inline bool cpu_has_virtual_nmis(void) { return vmcs_config.pin_based_exec_ctrl & PIN_BASED_VIRTUAL_NMIS && diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 6576935b9d43..83e846fb3fc8 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -812,6 +812,15 @@ static inline bool nested_vmx_prepare_msr_bitmap(struc= t kvm_vcpu *vcpu, nested_vmx_merge_msr_bitmaps_rw(MSR_FS_BASE); nested_vmx_merge_msr_bitmaps_rw(MSR_GS_BASE); nested_vmx_merge_msr_bitmaps_rw(MSR_KERNEL_GS_BASE); + nested_vmx_merge_msr_bitmaps_rw(MSR_IA32_FRED_RSP0); + nested_vmx_merge_msr_bitmaps_rw(MSR_IA32_FRED_RSP1); + nested_vmx_merge_msr_bitmaps_rw(MSR_IA32_FRED_RSP2); + nested_vmx_merge_msr_bitmaps_rw(MSR_IA32_FRED_RSP3); + nested_vmx_merge_msr_bitmaps_rw(MSR_IA32_FRED_STKLVLS); + nested_vmx_merge_msr_bitmaps_rw(MSR_IA32_FRED_SSP1); + nested_vmx_merge_msr_bitmaps_rw(MSR_IA32_FRED_SSP2); + nested_vmx_merge_msr_bitmaps_rw(MSR_IA32_FRED_SSP3); + nested_vmx_merge_msr_bitmaps_rw(MSR_IA32_FRED_CONFIG); #endif nested_vmx_merge_msr_bitmaps_rw(MSR_IA32_SPEC_CTRL); nested_vmx_merge_msr_bitmaps_write(MSR_IA32_PRED_CMD); @@ -1356,9 +1365,11 @@ static int vmx_restore_vmx_basic(struct vcpu_vmx *vm= x, u64 data) const u64 feature_bits =3D VMX_BASIC_DUAL_MONITOR_TREATMENT | VMX_BASIC_INOUT | VMX_BASIC_TRUE_CTLS | - VMX_BASIC_NO_HW_ERROR_CODE_CC; + VMX_BASIC_NO_HW_ERROR_CODE_CC | + VMX_BASIC_NESTED_EXCEPTION; =20 - const u64 reserved_bits =3D GENMASK_ULL(63, 57) | + const u64 reserved_bits =3D GENMASK_ULL(63, 59) | + BIT_ULL(57) | GENMASK_ULL(47, 45) | BIT_ULL(31); =20 @@ -2599,6 +2610,8 @@ static void prepare_vmcs02_early(struct vcpu_vmx *vmx= , struct loaded_vmcs *vmcs0 vmcs12->vm_entry_instruction_len); vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, vmcs12->guest_interruptibility_info); + if (cpu_has_vmx_fred()) + vmcs_write64(INJECTED_EVENT_DATA, vmcs12->injected_event_data); vmx->loaded_vmcs->nmi_known_unmasked =3D !(vmcs12->guest_interruptibility_info & GUEST_INTR_STATE_NMI); } else { @@ -2632,6 +2645,30 @@ static void vmcs_write_cet_state(struct kvm_vcpu *vc= pu, u64 s_cet, } } =20 +static void vmcs_read_fred_msrs(struct vmcs_fred_msrs *msrs) +{ + msrs->fred_config =3D vmcs_read64(GUEST_IA32_FRED_CONFIG); + msrs->fred_rsp1 =3D vmcs_read64(GUEST_IA32_FRED_RSP1); + msrs->fred_rsp2 =3D vmcs_read64(GUEST_IA32_FRED_RSP2); + msrs->fred_rsp3 =3D vmcs_read64(GUEST_IA32_FRED_RSP3); + msrs->fred_stklvls =3D vmcs_read64(GUEST_IA32_FRED_STKLVLS); + msrs->fred_ssp1 =3D vmcs_read64(GUEST_IA32_FRED_SSP1); + msrs->fred_ssp2 =3D vmcs_read64(GUEST_IA32_FRED_SSP2); + msrs->fred_ssp3 =3D vmcs_read64(GUEST_IA32_FRED_SSP3); +} + +static void vmcs_write_fred_msrs(struct vmcs_fred_msrs *msrs) +{ + vmcs_write64(GUEST_IA32_FRED_CONFIG, msrs->fred_config); + vmcs_write64(GUEST_IA32_FRED_RSP1, msrs->fred_rsp1); + vmcs_write64(GUEST_IA32_FRED_RSP2, msrs->fred_rsp2); + vmcs_write64(GUEST_IA32_FRED_RSP3, msrs->fred_rsp3); + vmcs_write64(GUEST_IA32_FRED_STKLVLS, msrs->fred_stklvls); + vmcs_write64(GUEST_IA32_FRED_SSP1, msrs->fred_ssp1); + vmcs_write64(GUEST_IA32_FRED_SSP2, msrs->fred_ssp2); + vmcs_write64(GUEST_IA32_FRED_SSP3, msrs->fred_ssp3); +} + static void prepare_vmcs02_rare(struct vcpu_vmx *vmx, struct vmcs12 *vmcs1= 2) { struct hv_enlightened_vmcs *hv_evmcs =3D nested_vmx_evmcs(vmx); @@ -2755,6 +2792,10 @@ static void prepare_vmcs02_rare(struct vcpu_vmx *vmx= , struct vmcs12 *vmcs12) vmcs12->guest_ssp, vmcs12->guest_ssp_tbl); =20 set_cr4_guest_host_mask(vmx); + + if (guest_cpu_cap_has(&vmx->vcpu, X86_FEATURE_FRED) && + nested_cpu_load_guest_fred_state(vmcs12)) + vmcs_write_fred_msrs(&vmcs12->guest_fred_msrs); } =20 /* @@ -2821,6 +2862,10 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, str= uct vmcs12 *vmcs12, vmcs_write64(GUEST_IA32_PAT, vcpu->arch.pat); } =20 + if (guest_cpu_cap_has(vcpu, X86_FEATURE_FRED) && + (!vmx->vcpu.arch.nested_run_pending || !nested_cpu_load_guest_fred_st= ate(vmcs12))) + vmcs_write_fred_msrs(&vmx->nested.pre_vmenter_fred_msrs); + vcpu->arch.tsc_offset =3D kvm_calc_nested_tsc_offset( vcpu->arch.l1_tsc_offset, vmx_get_l2_tsc_offset(vcpu), @@ -3630,7 +3675,8 @@ static int nested_vmx_check_permission(struct kvm_vcp= u *vcpu) } =20 static void load_vmcs12_host_state(struct kvm_vcpu *vcpu, - struct vmcs12 *vmcs12); + struct vmcs12 *vmcs12, + bool from_failed_vmentry); =20 /* * If from_vmentry is false, this is being called from state restore (eith= er RSM @@ -3680,6 +3726,10 @@ enum nvmx_vmentry_status nested_vmx_enter_non_root_m= ode(struct kvm_vcpu *vcpu, &vmx->nested.pre_vmenter_ssp, &vmx->nested.pre_vmenter_ssp_tbl); =20 + if (guest_cpu_cap_has(vcpu, X86_FEATURE_FRED) && + (!vmx->vcpu.arch.nested_run_pending || !nested_cpu_load_guest_fred_st= ate(vmcs12))) + vmcs_read_fred_msrs(&vmx->nested.pre_vmenter_fred_msrs); + /* * Stash L1's CR3, so that in the event of a "late" VM-Fail, i.e. a * VM-Fail detected by hardware but not KVM, KVM can unwind its @@ -3794,7 +3844,7 @@ enum nvmx_vmentry_status nested_vmx_enter_non_root_mo= de(struct kvm_vcpu *vcpu, =20 nested_put_vmcs12_pages(vcpu); =20 - load_vmcs12_host_state(vcpu, vmcs12); + load_vmcs12_host_state(vcpu, vmcs12, true); vmcs12->vm_exit_reason =3D exit_reason.full; if (enable_shadow_vmcs || nested_vmx_is_evmptr12_valid(vmx)) vmx->nested.need_vmcs12_to_shadow_sync =3D true; @@ -3983,6 +4033,8 @@ static void vmcs12_save_pending_event(struct kvm_vcpu= *vcpu, u32 idt_vectoring; unsigned int nr; =20 + vmcs12->original_event_data =3D 0; + /* * Per the SDM, VM-Exits due to double and triple faults are never * considered to occur during event delivery, even if the double/triple @@ -4021,6 +4073,13 @@ static void vmcs12_save_pending_event(struct kvm_vcp= u *vcpu, vcpu->arch.exception.error_code; } =20 + if ((vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE) && + (vmcs12->guest_cr4 & X86_CR4_FRED) && + (vcpu->arch.exception.is_nested)) + idt_vectoring |=3D VECTORING_INFO_NESTED_EXCEPTION_MASK; + + vmcs12->original_event_data =3D vcpu->arch.exception.event_data; + vmcs12->idt_vectoring_info_field =3D idt_vectoring; } else if (vcpu->arch.nmi_injected) { vmcs12->idt_vectoring_info_field =3D @@ -4744,6 +4803,15 @@ static void sync_vmcs02_to_vmcs12(struct kvm_vcpu *v= cpu, struct vmcs12 *vmcs12) vmcs_read_cet_state(&vmx->vcpu, &vmcs12->guest_s_cet, &vmcs12->guest_ssp, &vmcs12->guest_ssp_tbl); + + if (guest_cpu_cap_has(vcpu, X86_FEATURE_FRED)) { + vmcs_read_fred_msrs(&vmx->nested.at_vmexit_fred_msrs); + + if (nested_cpu_save_guest_fred_state(vmcs12)) + memcpy(&vmcs12->guest_fred_msrs, + &vmx->nested.at_vmexit_fred_msrs, + sizeof(struct vmcs_fred_msrs)); + } } =20 /* @@ -4788,6 +4856,21 @@ static void prepare_vmcs12(struct kvm_vcpu *vcpu, st= ruct vmcs12 *vmcs12, =20 vmcs12->vm_exit_intr_info =3D exit_intr_info; vmcs12->vm_exit_instruction_len =3D exit_insn_len; + + /* + * When there is a valid original event, the exiting event is a nested + * event during delivery of the earlier original event. + * + * FRED event delivery reflects this relationship by setting the value + * of the nested exception bit of VM-exit interruption information + * (aka exiting-event identification) to that of the valid bit of the + * IDT-vectoring information (aka original-event identification). + */ + if ((vmcs12->idt_vectoring_info_field & VECTORING_INFO_VALID_MASK) && + (vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE) && + (vmcs12->guest_cr4 & X86_CR4_FRED)) + vmcs12->vm_exit_intr_info |=3D INTR_INFO_NESTED_EXCEPTION_MASK; + vmcs12->vmx_instruction_info =3D vmcs_read32(VMX_INSTRUCTION_INFO); =20 /* @@ -4814,8 +4897,10 @@ static void prepare_vmcs12(struct kvm_vcpu *vcpu, st= ruct vmcs12 *vmcs12, * This function should be called when the active VMCS is L1's (vmcs01). */ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu, - struct vmcs12 *vmcs12) + struct vmcs12 *vmcs12, + bool from_failed_vmentry) { + struct vcpu_vmx *vmx =3D to_vmx(vcpu); enum vm_entry_failure_code ignored; struct kvm_segment seg; =20 @@ -4890,6 +4975,14 @@ static void load_vmcs12_host_state(struct kvm_vcpu *= vcpu, WARN_ON_ONCE(__kvm_emulate_msr_write(vcpu, MSR_CORE_PERF_GLOBAL_CTRL, vmcs12->host_ia32_perf_global_ctrl)); =20 + if (guest_cpu_cap_has(vcpu, X86_FEATURE_FRED)) { + if (nested_cpu_load_host_fred_state(vmcs12)) { + vmcs_write_fred_msrs(&vmcs12->host_fred_msrs); + } else if (!from_failed_vmentry) { + vmcs_write_fred_msrs(&vmx->nested.at_vmexit_fred_msrs); + } + } + /* Set L1 segment info according to Intel SDM 27.5.2 Loading Host Segment and Descriptor-Table Registers */ seg =3D (struct kvm_segment) { @@ -5209,7 +5302,7 @@ void __nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 v= m_exit_reason, vmcs12->vm_exit_intr_error_code, KVM_ISA_VMX); =20 - load_vmcs12_host_state(vcpu, vmcs12); + load_vmcs12_host_state(vcpu, vmcs12, false); =20 /* * Process events if an injectable IRQ or NMI is pending, even @@ -7370,6 +7463,8 @@ static void nested_vmx_setup_basic(struct nested_vmx_= msrs *msrs) msrs->basic |=3D VMX_BASIC_INOUT; if (cpu_has_vmx_basic_no_hw_errcode_cc()) msrs->basic |=3D VMX_BASIC_NO_HW_ERROR_CODE_CC; + if (cpu_has_vmx_nested_exception()) + msrs->basic |=3D VMX_BASIC_NESTED_EXCEPTION; } =20 static void nested_vmx_setup_cr_fixed(struct nested_vmx_msrs *msrs) diff --git a/arch/x86/kvm/vmx/nested.h b/arch/x86/kvm/vmx/nested.h index 371fc3498b12..dc5a1e9cb4e9 100644 --- a/arch/x86/kvm/vmx/nested.h +++ b/arch/x86/kvm/vmx/nested.h @@ -272,6 +272,23 @@ static inline bool nested_cpu_has_encls_exit(struct vm= cs12 *vmcs12) return nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENCLS_EXITING); } =20 +static inline bool nested_cpu_load_guest_fred_state(struct vmcs12 *vmcs12) +{ + return vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_FRED; +} + +static inline bool nested_cpu_save_guest_fred_state(struct vmcs12 *vmcs12) +{ + return nested_cpu_has_secondary_vm_exit_controls(vmcs12) && + vmcs12->secondary_vm_exit_controls & SECONDARY_VM_EXIT_SAVE_IA32_F= RED; +} + +static inline bool nested_cpu_load_host_fred_state(struct vmcs12 *vmcs12) +{ + return nested_cpu_has_secondary_vm_exit_controls(vmcs12) && + vmcs12->secondary_vm_exit_controls & SECONDARY_VM_EXIT_LOAD_IA32_F= RED; +} + /* * if fixed0[i] =3D=3D 1: val[i] must be 1 * if fixed1[i] =3D=3D 0: val[i] must be 0 diff --git a/arch/x86/kvm/vmx/vmcs.h b/arch/x86/kvm/vmx/vmcs.h index ca341c59bab1..58af10f73789 100644 --- a/arch/x86/kvm/vmx/vmcs.h +++ b/arch/x86/kvm/vmx/vmcs.h @@ -52,6 +52,17 @@ struct vmcs_controls_shadow { u64 tertiary_exec; }; =20 +struct vmcs_fred_msrs { + u64 fred_config; + u64 fred_rsp1; + u64 fred_rsp2; + u64 fred_rsp3; + u64 fred_stklvls; + u64 fred_ssp1; + u64 fred_ssp2; + u64 fred_ssp3; +}; + /* * Track a VMCS that may be loaded on a certain CPU. If it is (cpu!=3D-1),= also * remember whether it was VMLAUNCHed, and maintain a linked list of all V= MCSs diff --git a/arch/x86/kvm/vmx/vmcs12.c b/arch/x86/kvm/vmx/vmcs12.c index 9d64a89aff00..837cb3d568c3 100644 --- a/arch/x86/kvm/vmx/vmcs12.c +++ b/arch/x86/kvm/vmx/vmcs12.c @@ -67,6 +67,24 @@ static const u16 kvm_supported_vmcs12_field_offsets[] __= initconst =3D { FIELD64(HOST_IA32_EFER, host_ia32_efer), FIELD64(HOST_IA32_PERF_GLOBAL_CTRL, host_ia32_perf_global_ctrl), FIELD64(SECONDARY_VM_EXIT_CONTROLS, secondary_vm_exit_controls), + FIELD64(INJECTED_EVENT_DATA, injected_event_data), + FIELD64(ORIGINAL_EVENT_DATA, original_event_data), + FIELD64(GUEST_IA32_FRED_CONFIG, guest_ia32_fred_config), + FIELD64(GUEST_IA32_FRED_RSP1, guest_ia32_fred_rsp1), + FIELD64(GUEST_IA32_FRED_RSP2, guest_ia32_fred_rsp2), + FIELD64(GUEST_IA32_FRED_RSP3, guest_ia32_fred_rsp3), + FIELD64(GUEST_IA32_FRED_STKLVLS, guest_ia32_fred_stklvls), + FIELD64(GUEST_IA32_FRED_SSP1, guest_ia32_fred_ssp1), + FIELD64(GUEST_IA32_FRED_SSP2, guest_ia32_fred_ssp2), + FIELD64(GUEST_IA32_FRED_SSP3, guest_ia32_fred_ssp3), + FIELD64(HOST_IA32_FRED_CONFIG, host_ia32_fred_config), + FIELD64(HOST_IA32_FRED_RSP1, host_ia32_fred_rsp1), + FIELD64(HOST_IA32_FRED_RSP2, host_ia32_fred_rsp2), + FIELD64(HOST_IA32_FRED_RSP3, host_ia32_fred_rsp3), + FIELD64(HOST_IA32_FRED_STKLVLS, host_ia32_fred_stklvls), + FIELD64(HOST_IA32_FRED_SSP1, host_ia32_fred_ssp1), + FIELD64(HOST_IA32_FRED_SSP2, host_ia32_fred_ssp2), + FIELD64(HOST_IA32_FRED_SSP3, host_ia32_fred_ssp3), FIELD(PIN_BASED_VM_EXEC_CONTROL, pin_based_vm_exec_control), FIELD(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control), FIELD(EXCEPTION_BITMAP, exception_bitmap), diff --git a/arch/x86/kvm/vmx/vmcs12.h b/arch/x86/kvm/vmx/vmcs12.h index bb2f406be63d..c4c5cd3722a5 100644 --- a/arch/x86/kvm/vmx/vmcs12.h +++ b/arch/x86/kvm/vmx/vmcs12.h @@ -191,6 +191,27 @@ struct __packed vmcs12 { u16 host_gs_selector; u16 host_tr_selector; u16 guest_pml_index; + u16 padding16[1]; /* align to 64-bit boundary */ + struct vmcs_fred_msrs guest_fred_msrs; +#define guest_ia32_fred_config guest_fred_msrs.fred_config +#define guest_ia32_fred_rsp1 guest_fred_msrs.fred_rsp1 +#define guest_ia32_fred_rsp2 guest_fred_msrs.fred_rsp2 +#define guest_ia32_fred_rsp3 guest_fred_msrs.fred_rsp3 +#define guest_ia32_fred_stklvls guest_fred_msrs.fred_stklvls +#define guest_ia32_fred_ssp1 guest_fred_msrs.fred_ssp1 +#define guest_ia32_fred_ssp2 guest_fred_msrs.fred_ssp2 +#define guest_ia32_fred_ssp3 guest_fred_msrs.fred_ssp3 + struct vmcs_fred_msrs host_fred_msrs; +#define host_ia32_fred_config host_fred_msrs.fred_config +#define host_ia32_fred_rsp1 host_fred_msrs.fred_rsp1 +#define host_ia32_fred_rsp2 host_fred_msrs.fred_rsp2 +#define host_ia32_fred_rsp3 host_fred_msrs.fred_rsp3 +#define host_ia32_fred_stklvls host_fred_msrs.fred_stklvls +#define host_ia32_fred_ssp1 host_fred_msrs.fred_ssp1 +#define host_ia32_fred_ssp2 host_fred_msrs.fred_ssp2 +#define host_ia32_fred_ssp3 host_fred_msrs.fred_ssp3 + u64 injected_event_data; + u64 original_event_data; }; =20 /* @@ -373,6 +394,24 @@ static inline void vmx_check_vmcs12_offsets(void) CHECK_OFFSET(host_gs_selector, 992); CHECK_OFFSET(host_tr_selector, 994); CHECK_OFFSET(guest_pml_index, 996); + CHECK_OFFSET(guest_ia32_fred_config, 1000); + CHECK_OFFSET(guest_ia32_fred_rsp1, 1008); + CHECK_OFFSET(guest_ia32_fred_rsp2, 1016); + CHECK_OFFSET(guest_ia32_fred_rsp3, 1024); + CHECK_OFFSET(guest_ia32_fred_stklvls, 1032); + CHECK_OFFSET(guest_ia32_fred_ssp1, 1040); + CHECK_OFFSET(guest_ia32_fred_ssp2, 1048); + CHECK_OFFSET(guest_ia32_fred_ssp3, 1056); + CHECK_OFFSET(host_ia32_fred_config, 1064); + CHECK_OFFSET(host_ia32_fred_rsp1, 1072); + CHECK_OFFSET(host_ia32_fred_rsp2, 1080); + CHECK_OFFSET(host_ia32_fred_rsp3, 1088); + CHECK_OFFSET(host_ia32_fred_stklvls, 1096); + CHECK_OFFSET(host_ia32_fred_ssp1, 1104); + CHECK_OFFSET(host_ia32_fred_ssp2, 1112); + CHECK_OFFSET(host_ia32_fred_ssp3, 1120); + CHECK_OFFSET(injected_event_data, 1128); + CHECK_OFFSET(original_event_data, 1136); } =20 extern u16 vmcs12_field_offsets[] __ro_after_init; diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index 14fd3f57d5c1..cc1e4038cd44 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -182,6 +182,29 @@ struct nested_vmx { u64 pre_vmenter_ssp; u64 pre_vmenter_ssp_tbl; =20 + /* + * Used to snapshot FRED MSRs that may NOT be saved to vmcs12 as specified + * in the VM-Exit controls of vmcs12 configured by L1 VMM. + * + * FRED MSRs are *always* saved into vmcs02 because KVM always sets + * SECONDARY_VM_EXIT_SAVE_IA32_FRED. However an L1 VMM may choose to cle= ar + * this bit, resulting in FRED MSRs not being propagated to vmcs12 from + * vmcs02. When the L1 VMM sets SECONDARY_VM_EXIT_LOAD_IA32_FRED, this is + * not a problem, since KVM then immediately loads the host FRED MSRs of + * vmcs12 to the guest FRED MSRs of vmcs01. + * + * But if the L1 VMM clears SECONDARY_VM_EXIT_LOAD_IA32_FRED, KVM should + * retain the FRED MSRs, i.e., propagate the guest FRED MSRs of vmcs02 to + * the guest FRED MSRs of vmcs01. + * + * This structure stores guest FRED MSRs that an L1 VMM opts not to save + * during VM-Exits from L2 to L1. These MSRs may still be retained for + * running the L1 VMM if SECONDARY_VM_EXIT_LOAD_IA32_FRED is cleared in + * vmcs12. + */ + struct vmcs_fred_msrs pre_vmenter_fred_msrs; + struct vmcs_fred_msrs at_vmexit_fred_msrs; + u16 vpid02; u16 last_vpid; =20 --=20 2.43.0 From nobody Fri Sep 25 13:16:55 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) (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 802844CE698; Fri, 11 Sep 2026 21:43:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789163001; cv=none; b=dt4R17zMURJK6+MT+fc9VFPTTipcTDkmykVvi3RfsarbQwtlkQDavgUsx1gxgGTjPM54OHfiChQFogWYM8FKePl8uDo+VPVG7bmL2oh8XhxxwfMN1I2gQ/Aly8EDWCGBwsRIngipsqFsNuKYoaqURDtGCjZs6pEuOVwiKM83Vn4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789163001; c=relaxed/simple; bh=0aEzJ9qwYXcpOA7/qPgBgBQcHtUuHRHVJ72QgY84zwE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RiZxrgF8u9vSCG2rPYCjuYvrATsGnfJf61Q1ZciLMPnUxydiLKqbtGQdJHf7TmCWM2IHR00Gc4t/PF8O7JafPq+yBe5PUeF1eoOWNYKMA85Q5Wnu4MiyghZZPXVWHJVruvNsVApAfXmL0OrCcsePjXmWUoaDPba4SstFabr9+n8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=J1/9DqHs; arc=none smtp.client-ip=192.198.163.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="J1/9DqHs" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789162999; x=1820698999; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=0aEzJ9qwYXcpOA7/qPgBgBQcHtUuHRHVJ72QgY84zwE=; b=J1/9DqHs+lTkPrJb+K0+AIzd+2kvKJcOy4Z4oNYNF/n1kJjM/VGL1emf r2kCp+Xl+Y1CSYd37WVJSd9lJdlM1cE0jtNNJUR35U56YhyudSVSDN6km l50tL6S3NVSDfvZEyTebyNdp0kNDUEIq41lEr7YoZ+5n6HOsMwc7i1xSa XyeVeEcFe+0KUfkbCimiMWom1R+yp9l52P6rDvHBSZvoL0bEMHhjmKfAR MWI4a2RDxyeiUVv7gCvL7V5fjJPAPid3DP0zeXdoaHE2GNkMJ9aoQvB90 ekDaldI7dpIS3VyzRmqtTmxpw722oAwegO0ldHE8GpDf5HhGdwY5qxkyj A==; X-CSE-ConnectionGUID: qKTGQkaQSZODc0ETiHjxZg== X-CSE-MsgGUID: 3JGofwiXRrWctlR+7DGd/g== X-IronPort-AV: E=McAfee;i="6800,10657,11902"; a="88572863" X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="88572863" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Sep 2026 14:43:17 -0700 X-CSE-ConnectionGUID: fez44+cgTimXe6COkdDh3w== X-CSE-MsgGUID: wAoWrDJYQcymWLvmGGesAw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="272004276" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa007.jf.intel.com with ESMTP; 11 Sep 2026 14:43:16 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Paolo Bonzini , Sean Christopherson , Jonathan Corbet , Shuah Khan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Xin Li , Andy Lutomirski , Peter Zijlstra , Andrew Cooper , Tom Lendacky , Nikunj A Dadhania , Shivansh Dhiman , David Woodhouse , Chao Gao , Binbin Wu , Sohil Mehta , Zhao Liu , Yosry Ahmed , David Matlack , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v10 22/28] KVM: nVMX: Restrict event data VMCS fields to FRED-supported hosts Date: Fri, 11 Sep 2026 14:36:52 -0700 Message-ID: <20260911213659.2025974-23-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260911213659.2025974-1-sohil.mehta@intel.com> References: <20260911213659.2025974-1-sohil.mehta@intel.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 Prevent L1 from accessing the ORIGINAL_EVENT_DATA and INJECTED_EVENT_DATA VMCS fields via VMREAD or VMWRITE when FRED support is disabled or not present in KVM. Signed-off-by: Xin Li Signed-off-by: Sohil Mehta --- v10: - Split out of "KVM: nVMX: Guard SHADOW_FIELD_R[OW] macros with VMX feature checks" and renamed (Sean). --- arch/x86/kvm/vmx/vmcs12.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/kvm/vmx/vmcs12.c b/arch/x86/kvm/vmx/vmcs12.c index 837cb3d568c3..67c730e31465 100644 --- a/arch/x86/kvm/vmx/vmcs12.c +++ b/arch/x86/kvm/vmx/vmcs12.c @@ -222,6 +222,9 @@ static __init bool cpu_has_vmcs12_field(unsigned int id= x) case HOST_SSP: case HOST_INTR_SSP_TABLE: return cpu_has_load_cet_ctrl(); + VMCS12_CASE64(ORIGINAL_EVENT_DATA): + VMCS12_CASE64(INJECTED_EVENT_DATA): + return cpu_has_vmx_fred(); =20 /* KVM always emulates PML and the VMX preemption timer in software. */ case GUEST_PML_INDEX: --=20 2.43.0 From nobody Fri Sep 25 13:16:55 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) (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 61203497B73; Fri, 11 Sep 2026 21:43:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789163007; cv=none; b=WiuUY4S8PcaDvnZDY5SJeSw2gWcDqvZopxC7sBctZnCO4T0H/M7rgffoYZCJ28IYjBMb4YaCgtjmKhR1ZR2NmuM7y0753ZmuyRqwZm4x36caRhaqwtFXobtLuD2D+FfJUgvmsDMR71PFTvQ8ALVpzQ8kWz0+YshAFOLKzQTsA/k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789163007; c=relaxed/simple; bh=qBPhaYL2eGX6F2cOv/irJ12oCM1yADz+gsM+AZjtzgI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PT+fay4ZzWvNdXzbentf1dlYWtn2HUissGSVcoYjC4Vo1ODk8+M24q9IZ3kqhiNLgontuSBbcLhCbjjUtqXQkNPPl6FAF9HKolpSqoUUOfDuBZfFTMvS9Lje9QCNuthG/TXdnhSW/5Y/SYQqvbAyLwPOgjpWWXW2O3vBnOGWLFQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=d+uig2S+; arc=none smtp.client-ip=192.198.163.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="d+uig2S+" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789163007; x=1820699007; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=qBPhaYL2eGX6F2cOv/irJ12oCM1yADz+gsM+AZjtzgI=; b=d+uig2S+Ka+1zlFcEB5HkIIqBQuRhGZ5eyXL/R+xcGrrDZTFVCz+5LC+ P0PAXaXaqov7HRk9sK/Xf2v5Kz/KvVk3TRDl47yPJL2wcYGUTWwx/VS+v Ietnp4k79Bkf671y9JffWNa1bEdKV6kFiCUA2mVEZC//RqMLJmDEn925Q 99sVmB1QmQdPM9pBh+wZsXXmTo9y3/0RdkklLIZv0dvh3XaWIaBrXAr+a UeDd6rUgJQ3ZiHoash/+8w8MEs77+NcRJPmP962cWapAHO/3v96d2c41Q AviwOgapv6frjb0J8P+81IXmT8gmnNQHCNrCqfaXMdvUyBjRGyWNxE+KI A==; X-CSE-ConnectionGUID: jC/7S4gtT4iT/CIyeAAXBA== X-CSE-MsgGUID: XkArfR/iToaBkcpVOD8zSA== X-IronPort-AV: E=McAfee;i="6800,10657,11902"; a="88572891" X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="88572891" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Sep 2026 14:43:26 -0700 X-CSE-ConnectionGUID: tpv0T0VbS6u+iEi5b0S7pg== X-CSE-MsgGUID: 4/IXgPddSYSdHTELRhhzAw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="272004289" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa007.jf.intel.com with ESMTP; 11 Sep 2026 14:43:25 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Paolo Bonzini , Sean Christopherson , Jonathan Corbet , Shuah Khan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Xin Li , Andy Lutomirski , Peter Zijlstra , Andrew Cooper , Tom Lendacky , Nikunj A Dadhania , Shivansh Dhiman , David Woodhouse , Chao Gao , Binbin Wu , Sohil Mehta , Zhao Liu , Yosry Ahmed , David Matlack , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v10 23/28] KVM: nVMX: Shadow ORIGINAL_EVENT_DATA and INJECTED_EVENT_DATA fields Date: Fri, 11 Sep 2026 14:36:53 -0700 Message-ID: <20260911213659.2025974-24-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260911213659.2025974-1-sohil.mehta@intel.com> References: <20260911213659.2025974-1-sohil.mehta@intel.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 (Intel)" Add ORIGINAL_EVENT_DATA and INJECTED_EVENT_DATA to the list of shadowed VMCS fields. Shadowing these fields allows the L1 hypervisor to access them without triggering a VM-exit to L0, optimizing performance for nested virtualization workloads that frequently query or inject event data. Signed-off-by: Xin Li (Intel) Signed-off-by: Sohil Mehta --- v10: - Split out of "KVM: nVMX: Guard SHADOW_FIELD_R[OW] macros with VMX feature checks" (Sean). --- arch/x86/kvm/vmx/vmcs_shadow_fields.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/x86/kvm/vmx/vmcs_shadow_fields.h b/arch/x86/kvm/vmx/vmcs_= shadow_fields.h index 67e821c2be6d..bdd56f3ca6c3 100644 --- a/arch/x86/kvm/vmx/vmcs_shadow_fields.h +++ b/arch/x86/kvm/vmx/vmcs_shadow_fields.h @@ -74,6 +74,10 @@ SHADOW_FIELD_RW(HOST_GS_BASE, host_gs_base) /* 64-bit */ SHADOW_FIELD_RO(GUEST_PHYSICAL_ADDRESS, guest_physical_address) SHADOW_FIELD_RO(GUEST_PHYSICAL_ADDRESS_HIGH, guest_physical_address) +SHADOW_FIELD_RO(ORIGINAL_EVENT_DATA, original_event_data) +SHADOW_FIELD_RO(ORIGINAL_EVENT_DATA_HIGH, original_event_data) +SHADOW_FIELD_RW(INJECTED_EVENT_DATA, injected_event_data) +SHADOW_FIELD_RW(INJECTED_EVENT_DATA_HIGH, injected_event_data) #endif =20 #undef SHADOW_FIELD_RO --=20 2.43.0 From nobody Fri Sep 25 13:16:55 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) (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 3C575497B89; Fri, 11 Sep 2026 21:43:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789163017; cv=none; b=TuQ9dmEjjWEDSlRgQ+dn7/miI6iEHALrS5lklNe7KkACydo13y0HThXkR1HVMJy+LGhaD2+ivOGhG62O69CSTzw+iZoc1nUg4YpxYCHjwqCXM1QY3JnH1R3jYzzNIVuS3JdN1r0ESNX7ws0fvBFzVn2uKLWyiAOCkaw0IccIZU8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789163017; c=relaxed/simple; bh=wwygfbCSXr4RW1gAi7ShHCivUHSxX9lkjMwzOGhDuR0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=t0gx+WuPc7/qGRv/vBvEGkCq6IgV/rcI3VOt3R4azMI0WbEG7x8+2uDk65jB9rjqB+TcJtURvnVr54PSp/7aWBW9APzUwdNBmeOAHlfNylWYKGt5CCRWu3wpSi5l05fsOHU16YF5gFxV5ssNyfl/EpIkitdUpQG80WAHMSNnSJo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=blHvtuxj; arc=none smtp.client-ip=192.198.163.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="blHvtuxj" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789163014; x=1820699014; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=wwygfbCSXr4RW1gAi7ShHCivUHSxX9lkjMwzOGhDuR0=; b=blHvtuxjkscOdVDjiQ+jzpkfhJWll2WeTT4FFhurG+XNeXZWvLCMw0IJ tOnwC4ZPhK2kKvXzJeNZEiqt83FAERYQ4N5A4upEHnomxoRQNXU50o821 yXh5/NAiKvFwn3pwXZNJske3sm8hrsoOpRQ6ERne5EPUXdeTaubVyIqkd /Zz20TMi6Xc3Y+gQQs5TPp47baHQstMDkn6HQHbMnIfUHE3PtqeiT8aU8 f2tfY5nifWuaHpek+lIwitRXHoFRZQBdOmVqFOOUXtlWZlLZl9CjjmH5l IfoObM+i3zlnNkR9E+qAnCAGRB9g4E6R+bR1yWRBQLOGdIjl/MEzFy7Dz A==; X-CSE-ConnectionGUID: LB7O/fhNQe68vJA42UgVBw== X-CSE-MsgGUID: tK5d7VmXRb2TjEp2O9Auhg== X-IronPort-AV: E=McAfee;i="6800,10657,11902"; a="88572910" X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="88572910" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Sep 2026 14:43:34 -0700 X-CSE-ConnectionGUID: X+b7zeVSSrOSAD8PBLv5xg== X-CSE-MsgGUID: JTqZ9NtVTPGL2WAB1TQpYQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="272004312" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa007.jf.intel.com with ESMTP; 11 Sep 2026 14:43:33 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Paolo Bonzini , Sean Christopherson , Jonathan Corbet , Shuah Khan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Xin Li , Andy Lutomirski , Peter Zijlstra , Andrew Cooper , Tom Lendacky , Nikunj A Dadhania , Shivansh Dhiman , David Woodhouse , Chao Gao , Binbin Wu , Sohil Mehta , Zhao Liu , Yosry Ahmed , David Matlack , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v10 24/28] KVM: nVMX: Validate FRED-related VMCS fields Date: Fri, 11 Sep 2026 14:36:54 -0700 Message-ID: <20260911213659.2025974-25-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260911213659.2025974-1-sohil.mehta@intel.com> References: <20260911213659.2025974-1-sohil.mehta@intel.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 (Intel)" Extend nested VMX field validation to include FRED-specific VMCS fields, mirroring hardware behavior. This enables support for nested FRED by ensuring control and guest/host state fields are properly checked. Signed-off-by: Xin Li (Intel) Signed-off-by: Sohil Mehta --- v10: - Use has_nested_exception to describe the event being injected rather than the CPU capability, for consistency with has_error_code (Chao). - Restructure the interruption-information checks into a switch on the interruption type (Chao). - Add a CC() statement to the reserved interruption type check so a VM-entry failure can be correlated with a specific check (Chao). - Reject the nested-exception bit (bit 13) for interruption types other than hardware exception, and fold in the nested-exception capability check. - Bound the "other event" vector explicitly instead of relying on a default arm. - Reject a zero VM-entry instruction length when injecting SYSCALL or SYSENTER if the vCPU doesn't enumerate zero-length instruction injection. --- arch/x86/kvm/vmx/nested.c | 119 +++++++++++++++++++++++++++++++++----- arch/x86/kvm/vmx/nested.h | 5 ++ 2 files changed, 111 insertions(+), 13 deletions(-) diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 83e846fb3fc8..3e0a1ed6440d 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -3111,6 +3111,8 @@ static int nested_check_vm_entry_controls(struct kvm_= vcpu *vcpu, struct vmcs12 *vmcs12) { struct vcpu_vmx *vmx =3D to_vmx(vcpu); + bool fred_enabled =3D (vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE) && + (vmcs12->guest_cr4 & X86_CR4_FRED); =20 if (CC(!vmx_control_verify(vmcs12->vm_entry_controls, vmx->nested.msrs.entry_ctls_low, @@ -3128,22 +3130,11 @@ static int nested_check_vm_entry_controls(struct kv= m_vcpu *vcpu, u8 vector =3D intr_info & INTR_INFO_VECTOR_MASK; u32 intr_type =3D intr_info & INTR_INFO_INTR_TYPE_MASK; bool has_error_code =3D intr_info & INTR_INFO_DELIVER_CODE_MASK; + bool has_nested_exception =3D intr_info & INTR_INFO_NESTED_EXCEPTION_MAS= K; bool urg =3D nested_cpu_has2(vmcs12, SECONDARY_EXEC_UNRESTRICTED_GUEST); bool prot_mode =3D !urg || vmcs12->guest_cr0 & X86_CR0_PE; =20 - /* VM-entry interruption-info field: interruption type */ - if (CC(intr_type =3D=3D INTR_TYPE_RESERVED) || - CC(intr_type =3D=3D INTR_TYPE_OTHER_EVENT && - !nested_cpu_supports_monitor_trap_flag(vcpu))) - return -EINVAL; - - /* VM-entry interruption-info field: vector */ - if (CC(intr_type =3D=3D INTR_TYPE_NMI_INTR && vector !=3D NMI_VECTOR) || - CC(intr_type =3D=3D INTR_TYPE_HARD_EXCEPTION && vector > 31) || - CC(intr_type =3D=3D INTR_TYPE_OTHER_EVENT && vector !=3D 0)) - return -EINVAL; - /* * Cannot deliver error code in real mode or if the interrupt * type is not hardware exception. For other cases, do the @@ -3167,8 +3158,28 @@ static int nested_check_vm_entry_controls(struct kvm= _vcpu *vcpu, if (CC(intr_info & INTR_INFO_RESVD_BITS_MASK)) return -EINVAL; =20 - /* VM-entry instruction length */ + if (CC(intr_type =3D=3D INTR_TYPE_RESERVED)) + return -EINVAL; + + /* + * Only for hardware exceptions and when the CPU enumerates + * VMX nested-exception support, bit 13 (indicating a nested + * exception) has value 1. Otherwise it is reserved. + */ + if (CC(has_nested_exception && + (intr_type !=3D INTR_TYPE_HARD_EXCEPTION || + !nested_cpu_has_nested_exception(vcpu)))) + return -EINVAL; + switch (intr_type) { + case INTR_TYPE_NMI_INTR: + if (CC(vector !=3D NMI_VECTOR)) + return -EINVAL; + break; + case INTR_TYPE_HARD_EXCEPTION: + if (CC(vector > 31)) + return -EINVAL; + break; case INTR_TYPE_SOFT_EXCEPTION: case INTR_TYPE_SOFT_INTR: case INTR_TYPE_PRIV_SW_EXCEPTION: @@ -3176,6 +3187,28 @@ static int nested_check_vm_entry_controls(struct kvm= _vcpu *vcpu, CC(vmcs12->vm_entry_instruction_len =3D=3D 0 && CC(!nested_cpu_has_zero_length_injection(vcpu)))) return -EINVAL; + break; + case INTR_TYPE_OTHER_EVENT: + if (CC(vector > 2)) + return -EINVAL; + + switch (vector) { + case 0: + if (CC(!nested_cpu_supports_monitor_trap_flag(vcpu))) + return -EINVAL; + break; + case 1: + case 2: + if (CC(!fred_enabled)) + return -EINVAL; + if (CC(vmcs12->vm_entry_instruction_len > X86_MAX_INSTRUCTION_LENGTH)) + return -EINVAL; + if (CC(vmcs12->vm_entry_instruction_len =3D=3D 0 && + !nested_cpu_has_zero_length_injection(vcpu))) + return -EINVAL; + break; + } + break; } } =20 @@ -3262,9 +3295,27 @@ static int nested_vmx_check_host_state(struct kvm_vc= pu *vcpu, if (ia32e) { if (CC(!(vmcs12->host_cr4 & X86_CR4_PAE))) return -EINVAL; + if (nested_cpu_load_host_fred_state(vmcs12)) { + if (CC(vmcs12->host_ia32_fred_config & FRED_CONFIG_RESERVED) || + CC(vmcs12->host_ia32_fred_rsp1 & GENMASK_ULL(5, 0)) || + CC(vmcs12->host_ia32_fred_rsp2 & GENMASK_ULL(5, 0)) || + CC(vmcs12->host_ia32_fred_rsp3 & GENMASK_ULL(5, 0)) || + CC(vmcs12->host_ia32_fred_ssp1 & GENMASK_ULL(2, 0)) || + CC(vmcs12->host_ia32_fred_ssp2 & GENMASK_ULL(2, 0)) || + CC(vmcs12->host_ia32_fred_ssp3 & GENMASK_ULL(2, 0)) || + CC(is_noncanonical_msr_address(vmcs12->host_ia32_fred_config & PAGE= _MASK, vcpu)) || + CC(is_noncanonical_msr_address(vmcs12->host_ia32_fred_rsp1, vcpu)) = || + CC(is_noncanonical_msr_address(vmcs12->host_ia32_fred_rsp2, vcpu)) = || + CC(is_noncanonical_msr_address(vmcs12->host_ia32_fred_rsp3, vcpu)) = || + CC(is_noncanonical_msr_address(vmcs12->host_ia32_fred_ssp1, vcpu)) = || + CC(is_noncanonical_msr_address(vmcs12->host_ia32_fred_ssp2, vcpu)) = || + CC(is_noncanonical_msr_address(vmcs12->host_ia32_fred_ssp3, vcpu))) + return -EINVAL; + } } else { if (CC(vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE) || CC(vmcs12->host_cr4 & X86_CR4_PCIDE) || + CC(vmcs12->host_cr4 & X86_CR4_FRED) || CC((vmcs12->host_rip) >> 32)) return -EINVAL; } @@ -3447,6 +3498,48 @@ static int nested_vmx_check_guest_state(struct kvm_v= cpu *vcpu, CC((vmcs12->guest_bndcfgs & MSR_IA32_BNDCFGS_RSVD)))) return -EINVAL; =20 + if (ia32e) { + if (nested_cpu_load_guest_fred_state(vmcs12)) { + if (CC(vmcs12->guest_ia32_fred_config & FRED_CONFIG_RESERVED) || + CC(vmcs12->guest_ia32_fred_rsp1 & GENMASK_ULL(5, 0)) || + CC(vmcs12->guest_ia32_fred_rsp2 & GENMASK_ULL(5, 0)) || + CC(vmcs12->guest_ia32_fred_rsp3 & GENMASK_ULL(5, 0)) || + CC(vmcs12->guest_ia32_fred_ssp1 & GENMASK_ULL(2, 0)) || + CC(vmcs12->guest_ia32_fred_ssp2 & GENMASK_ULL(2, 0)) || + CC(vmcs12->guest_ia32_fred_ssp3 & GENMASK_ULL(2, 0)) || + CC(is_noncanonical_msr_address(vmcs12->guest_ia32_fred_config & PAG= E_MASK, vcpu)) || + CC(is_noncanonical_msr_address(vmcs12->guest_ia32_fred_rsp1, vcpu))= || + CC(is_noncanonical_msr_address(vmcs12->guest_ia32_fred_rsp2, vcpu))= || + CC(is_noncanonical_msr_address(vmcs12->guest_ia32_fred_rsp3, vcpu))= || + CC(is_noncanonical_msr_address(vmcs12->guest_ia32_fred_ssp1, vcpu))= || + CC(is_noncanonical_msr_address(vmcs12->guest_ia32_fred_ssp2, vcpu))= || + CC(is_noncanonical_msr_address(vmcs12->guest_ia32_fred_ssp3, vcpu))) + return -EINVAL; + } + if (vmcs12->guest_cr4 & X86_CR4_FRED) { + unsigned int ss_dpl =3D VMX_AR_DPL(vmcs12->guest_ss_ar_bytes); + + if (CC(ss_dpl =3D=3D 1 || ss_dpl =3D=3D 2)) + return -EINVAL; + + switch (ss_dpl) { + case 0: + if (CC(!(vmcs12->guest_cs_ar_bytes & VMX_AR_L_MASK))) + return -EINVAL; + break; + case 3: + if (CC(vmcs12->guest_rflags & X86_EFLAGS_IOPL)) + return -EINVAL; + if (CC(vmcs12->guest_interruptibility_info & GUEST_INTR_STATE_STI)) + return -EINVAL; + break; + } + } + } else { + if (CC(vmcs12->guest_cr4 & X86_CR4_FRED)) + return -EINVAL; + } + if (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_CET_STATE) { if (nested_vmx_check_cet_state_common(vcpu, vmcs12->guest_s_cet, vmcs12->guest_ssp, diff --git a/arch/x86/kvm/vmx/nested.h b/arch/x86/kvm/vmx/nested.h index dc5a1e9cb4e9..551121824128 100644 --- a/arch/x86/kvm/vmx/nested.h +++ b/arch/x86/kvm/vmx/nested.h @@ -334,6 +334,11 @@ static inline bool nested_cpu_has_no_hw_errcode_cc(str= uct kvm_vcpu *vcpu) return to_vmx(vcpu)->nested.msrs.basic & VMX_BASIC_NO_HW_ERROR_CODE_CC; } =20 +static inline bool nested_cpu_has_nested_exception(struct kvm_vcpu *vcpu) +{ + return to_vmx(vcpu)->nested.msrs.basic & VMX_BASIC_NESTED_EXCEPTION; +} + /* No difference in the restrictions on guest and host CR4 in VMX operatio= n. */ #define nested_guest_cr4_valid nested_cr4_valid #define nested_host_cr4_valid nested_cr4_valid --=20 2.43.0 From nobody Fri Sep 25 13:16:55 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) (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 11AB0497B96; Fri, 11 Sep 2026 21:43:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789163024; cv=none; b=CKurdllmC9MNI4aaJKdoIT0gE/kV1cOiotqEK+WugnKW3ZSx8K5m29lG+KxDPWhbGpMH5TZgNJL39YuOMRAX5IiGkEv5MUKiDZfj/aJeAy7E//b+VCP+S94vqbi+jfMph86a77O2azC6L36DE77E5iDCHRUDaxk1jKL5D8d6Gnk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789163024; c=relaxed/simple; bh=u/9qQB+51ZA54dIgotA961NlEY+IOivKPseuq1clEso=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=De+3/5J1Uy+T5BLTICj8p2HAb9/l6oP1q0kBqAwUJI0VG+7GOaMyacpsbc6PsZHXJGPhmEOU6wLPURRnNrR/D5NznXIsIofqlRTax7AXrPgjVpWsKX3LQsXmtE2HUPz9SPNUIkhOr2UH5RPQMYO+2BXyZTrbYGQznQl7C9Nz/QU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=HajxN4B2; arc=none smtp.client-ip=192.198.163.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="HajxN4B2" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789163022; x=1820699022; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=u/9qQB+51ZA54dIgotA961NlEY+IOivKPseuq1clEso=; b=HajxN4B2UqebvQxhsydi1k/6lR0QsUt4wcM67H/JX1955XIhEnlbqZ6P Ff5mKo+dZ6VVX7ywjtuoWCVhDogzkZpBW+ptxOcWs6H26p6LoBfixF1nj rxM5iGyO0l85JX7pEaGbc0x0f/xiYSwPHcGQ9TSx+D+DhaHdY4r3ZapOR cmgsHiNot5KVVRcVb7+pionJ0NA5APB80fk8bqrNVIH6JXxUEQ9bhtzbo B3nHhStA3PaYUs0HfJaqoIuIf8BcZGbO4JqHhE+7taVtACXgsbvTWwNS+ PW0Ytb+7t7fmhETWK78yPUeb12Z8OmqAZS+64fU3e51nbjDA96P/0cdD3 w==; X-CSE-ConnectionGUID: dC7GaMFESViUi8k0ryGxCg== X-CSE-MsgGUID: S2v95pE/SDC3Oh0C178IyQ== X-IronPort-AV: E=McAfee;i="6800,10657,11902"; a="88572919" X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="88572919" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Sep 2026 14:43:42 -0700 X-CSE-ConnectionGUID: 755rMGAsRjuRGYyz/NwHjg== X-CSE-MsgGUID: X5BupmnMQd61URu1z532xQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="272004338" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa007.jf.intel.com with ESMTP; 11 Sep 2026 14:43:41 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Paolo Bonzini , Sean Christopherson , Jonathan Corbet , Shuah Khan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Xin Li , Andy Lutomirski , Peter Zijlstra , Andrew Cooper , Tom Lendacky , Nikunj A Dadhania , Shivansh Dhiman , David Woodhouse , Chao Gao , Binbin Wu , Sohil Mehta , Zhao Liu , Yosry Ahmed , David Matlack , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v10 25/28] KVM: nVMX: Enable VMX FRED controls Date: Fri, 11 Sep 2026 14:36:55 -0700 Message-ID: <20260911213659.2025974-26-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260911213659.2025974-1-sohil.mehta@intel.com> References: <20260911213659.2025974-1-sohil.mehta@intel.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 (Intel)" Permit use of VMX FRED controls in nested VMX now that support for nested FRED is implemented. Signed-off-by: Xin Li (Intel) Signed-off-by: Sohil Mehta Reviewed-by: Chao Gao --- v10: - Remove an obsolete comment (Chao). --- arch/x86/kvm/vmx/nested.c | 10 +++------- arch/x86/kvm/vmx/vmx.c | 1 + 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 3e0a1ed6440d..4fad9728a2ea 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -7371,12 +7371,8 @@ static void nested_vmx_setup_exit_ctls(struct vmcs_c= onfig *vmcs_conf, =20 if (msrs->exit_ctls_high & VM_EXIT_ACTIVATE_SECONDARY_CONTROLS) { msrs->secondary_exit_ctls =3D vmcs_conf->vmexit_2nd_ctrl; - /* - * As the secondary VM exit control is always loaded, do not - * advertise any feature in it to nVMX until its nVMX support - * is ready. - */ - msrs->secondary_exit_ctls &=3D 0; + msrs->secondary_exit_ctls &=3D SECONDARY_VM_EXIT_SAVE_IA32_FRED | + SECONDARY_VM_EXIT_LOAD_IA32_FRED; } } =20 @@ -7392,7 +7388,7 @@ static void nested_vmx_setup_entry_ctls(struct vmcs_c= onfig *vmcs_conf, VM_ENTRY_IA32E_MODE | #endif VM_ENTRY_LOAD_IA32_PAT | VM_ENTRY_LOAD_BNDCFGS | - VM_ENTRY_LOAD_CET_STATE; + VM_ENTRY_LOAD_CET_STATE | VM_ENTRY_LOAD_IA32_FRED; msrs->entry_ctls_high |=3D (VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR | VM_ENTRY_LOAD_IA32_EFER | VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL); diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 3a3315a7fc11..f673cd4e8956 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -8150,6 +8150,7 @@ static void nested_vmx_cr_fixed1_bits_update(struct k= vm_vcpu *vcpu) =20 entry =3D kvm_find_cpuid_entry_index(vcpu, 0x7, 1); cr4_fixed1_update(X86_CR4_LAM_SUP, eax, feature_bit(LAM)); + cr4_fixed1_update(X86_CR4_FRED, eax, feature_bit(FRED)); =20 #undef cr4_fixed1_update } --=20 2.43.0 From nobody Fri Sep 25 13:16:55 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) (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 55AC44BEE3B; Fri, 11 Sep 2026 21:43:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789163033; cv=none; b=cqNWP+L0dLIM+0dVkiygbw9khuTfU4RiUjaTchAepKLHYIoBRjGxypzjC+4cZWeVACG5spgDbGE4iBt+pCkbRoTnZ7P3FkyGkjDH/ypM0FmmVUpWk/U7PMY+YOpVsHpSBBeYPNWoRBgp/oFo1MqgoZkL2TgqmzwUUk+iA4j5b3s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789163033; c=relaxed/simple; bh=xTcz+8SJvIkx43QiWYnGAhgtbnaSw9N12NLUCq9wllo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qT+RxCosfa/Te+9xk82AZlEn2KOmN8E2didb2qFRMtpRvWg8EKqh6wtw+Du+Ug1LoLF0wTGtIpTfah6pbwxLpI/FgA3ulFHgDFyL2IVBrVLpmFuMv04W2yKLCEpRr8V8v/vlflVq1VKjdti1csn80DR3iaKGsz9LTgoEsAYK60M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=mf/Unxai; arc=none smtp.client-ip=192.198.163.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="mf/Unxai" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789163033; x=1820699033; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=xTcz+8SJvIkx43QiWYnGAhgtbnaSw9N12NLUCq9wllo=; b=mf/Unxaiz1DR/1r0oGmSqq5aPv5BqtVoFEc6HWkq1h25VZOd7mfarb9z K5kftWMOGO9ioM++88KvNdm+JGoa/OgYxBCVHJqhGfj1mEJ6EbffEaMso u18B6pl+3aXK4bsaJJRmZnR862Et8exCfjW67hgZY/1yS2drhilSPBEhE bKCtQ/QLaeEw7Povv2Q+5mCOAmY+/xiLzcq9Kb0Ercgat6f2nXPdXSHz/ bw6Kt+LIn86kEv7NRj+pvIXu9vFoRnoTvCqXIRagcBv8Es66yAcuTHpzj M1clH34fvO2CIv2iVRBnioOD3E4WbrsGhwD3eN2n20BAXEYVUdMrrZUQ/ Q==; X-CSE-ConnectionGUID: NnPAQhLfSJyAWH8Dv4n3rA== X-CSE-MsgGUID: 9vEqNf/kTTqRY5jEPaKWrw== X-IronPort-AV: E=McAfee;i="6800,10657,11902"; a="88572932" X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="88572932" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Sep 2026 14:43:52 -0700 X-CSE-ConnectionGUID: ZxDSJ2FLRzyNkuPE9JxAcQ== X-CSE-MsgGUID: G+1GdaUyRFuRBOyaOwsMhw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="272004368" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa007.jf.intel.com with ESMTP; 11 Sep 2026 14:43:51 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Paolo Bonzini , Sean Christopherson , Jonathan Corbet , Shuah Khan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Xin Li , Andy Lutomirski , Peter Zijlstra , Andrew Cooper , Tom Lendacky , Nikunj A Dadhania , Shivansh Dhiman , David Woodhouse , Chao Gao , Binbin Wu , Sohil Mehta , Zhao Liu , Yosry Ahmed , David Matlack , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v10 26/28] KVM: selftests: Add FRED MSRs to msrs_test Date: Fri, 11 Sep 2026 14:36:56 -0700 Message-ID: <20260911213659.2025974-27-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260911213659.2025974-1-sohil.mehta@intel.com> References: <20260911213659.2025974-1-sohil.mehta@intel.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 Add FRED MSR coverage to msrs_test, including the FRED RSP0-3, SSP0-3, STKLVLS and CONFIG MSRs. Signed-off-by: Xin Li Signed-off-by: Sohil Mehta --- v10: - New patch. --- tools/arch/x86/include/asm/msr-index.h | 2 + .../selftests/kvm/include/x86/processor.h | 1 + tools/testing/selftests/kvm/x86/msrs_test.c | 52 ++++++++++++++++++- 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/tools/arch/x86/include/asm/msr-index.h b/tools/arch/x86/includ= e/asm/msr-index.h index 18c4be75e927..14632e29f981 100644 --- a/tools/arch/x86/include/asm/msr-index.h +++ b/tools/arch/x86/include/asm/msr-index.h @@ -64,6 +64,8 @@ #define MSR_IA32_FRED_SSP3 0x1d3 /* Level 3 shadow stack pointer */ #define MSR_IA32_FRED_CONFIG 0x1d4 /* Entrypoint and interrupt stack lev= el */ =20 +#define FRED_CONFIG_RESERVED (BIT_ULL(2) | GENMASK_ULL(5, 4) | BIT_ULL(11= )) + /* Intel MSRs. Some also available on other CPUs */ #define MSR_TEST_CTRL 0x00000033 #define MSR_TEST_CTRL_SPLIT_LOCK_DETECT_BIT 29 diff --git a/tools/testing/selftests/kvm/include/x86/processor.h b/tools/te= sting/selftests/kvm/include/x86/processor.h index 6e6f70035508..916646cb4d89 100644 --- a/tools/testing/selftests/kvm/include/x86/processor.h +++ b/tools/testing/selftests/kvm/include/x86/processor.h @@ -195,6 +195,7 @@ struct kvm_x86_cpu_feature { #define X86_FEATURE_SPEC_CTRL KVM_X86_CPU_FEATURE(0x7, 0, EDX, 26) #define X86_FEATURE_ARCH_CAPABILITIES KVM_X86_CPU_FEATURE(0x7, 0, EDX, 29) #define X86_FEATURE_PKS KVM_X86_CPU_FEATURE(0x7, 0, ECX, 31) +#define X86_FEATURE_FRED KVM_X86_CPU_FEATURE(0x7, 1, EAX, 17) #define X86_FEATURE_XTILECFG KVM_X86_CPU_FEATURE(0xD, 0, EAX, 17) #define X86_FEATURE_XTILEDATA KVM_X86_CPU_FEATURE(0xD, 0, EAX, 18) #define X86_FEATURE_XSAVES KVM_X86_CPU_FEATURE(0xD, 1, EAX, 3) diff --git a/tools/testing/selftests/kvm/x86/msrs_test.c b/tools/testing/se= lftests/kvm/x86/msrs_test.c index f7e39bf887ad..6e2d8b8f1bd3 100644 --- a/tools/testing/selftests/kvm/x86/msrs_test.c +++ b/tools/testing/selftests/kvm/x86/msrs_test.c @@ -60,9 +60,23 @@ static const u64 u64_val =3D 0xaaaa5555aaaa5555ull; #define MSR_TEST_CANONICAL(msr, feat) \ __MSR_TEST(msr, #msr, canonical_val, NONCANONICAL, 0, feat) =20 +#define MSR_TEST_CANONICAL2(msr, feat, f2) \ + ____MSR_TEST(msr, #msr, canonical_val, NONCANONICAL, 0, feat, f2, false) + #define MSR_TEST_KVM(msr, val, rsvd, feat) \ ____MSR_TEST(KVM_REG_ ##msr, #msr, val, rsvd, 0, feat, feat, true) =20 +/* FRED RSPs are 64-byte aligned, thus bits 5:0 are all zero */ +static const u64 fred_rsp_canonical_val =3D canonical_val + 0xbc0; + +/* + * FRED SSP[123] are 8-byte aligned, thus bits 2:0 are all zero. + * + * For legacy reasons, FRED SSP0 is allowed to be 4-byte aligned, but treat + * it as 8-byte aligned to simplify the tests. + */ +static const u64 fred_ssp_canonical_val =3D canonical_val + 0xbc8; + /* * The main struct must be scoped to a function due to the use of structur= es to * define features. For the global structure, allocate enough space for t= he @@ -388,8 +402,9 @@ static void test_msrs(void) MSR_TEST2(MSR_IA32_S_CET, CET_ENDBR_EN, CET_RESERVED, IBT, SHSTK), MSR_TEST2(MSR_IA32_U_CET, CET_SHSTK_EN, CET_RESERVED, SHSTK, IBT), MSR_TEST2(MSR_IA32_U_CET, CET_ENDBR_EN, CET_RESERVED, IBT, SHSTK), - MSR_TEST_CANONICAL(MSR_IA32_PL0_SSP, SHSTK), - MSR_TEST(MSR_IA32_PL0_SSP, canonical_val, canonical_val | 1, SHSTK), + MSR_TEST_CANONICAL2(MSR_IA32_PL0_SSP, SHSTK, FRED), + MSR_TEST2(MSR_IA32_PL0_SSP, canonical_val, canonical_val | 1, SHSTK, FRE= D), + MSR_TEST2(MSR_IA32_PL0_SSP, canonical_val, canonical_val | 1, FRED, SHST= K), MSR_TEST_CANONICAL(MSR_IA32_PL1_SSP, SHSTK), MSR_TEST(MSR_IA32_PL1_SSP, canonical_val, canonical_val | 1, SHSTK), MSR_TEST_CANONICAL(MSR_IA32_PL2_SSP, SHSTK), @@ -398,10 +413,35 @@ static void test_msrs(void) MSR_TEST(MSR_IA32_PL3_SSP, canonical_val, canonical_val | 1, SHSTK), =20 MSR_TEST_KVM(GUEST_SSP, canonical_val, NONCANONICAL, SHSTK), + + MSR_TEST_CANONICAL(MSR_IA32_FRED_RSP0, FRED), + MSR_TEST(MSR_IA32_FRED_RSP0, fred_rsp_canonical_val, fred_rsp_canonical_= val | 1, FRED), + MSR_TEST_CANONICAL(MSR_IA32_FRED_RSP1, FRED), + MSR_TEST(MSR_IA32_FRED_RSP1, fred_rsp_canonical_val, fred_rsp_canonical_= val | 2, FRED), + MSR_TEST_CANONICAL(MSR_IA32_FRED_RSP2, FRED), + MSR_TEST(MSR_IA32_FRED_RSP2, fred_rsp_canonical_val, fred_rsp_canonical_= val | 4, FRED), + MSR_TEST_CANONICAL(MSR_IA32_FRED_RSP3, FRED), + MSR_TEST(MSR_IA32_FRED_RSP3, fred_rsp_canonical_val, fred_rsp_canonical_= val | 7, FRED), + + MSR_TEST_CANONICAL2(MSR_IA32_FRED_SSP0, FRED, SHSTK), + MSR_TEST2(MSR_IA32_FRED_SSP0, fred_ssp_canonical_val, fred_ssp_canonical= _val | 1, SHSTK, FRED), + MSR_TEST2(MSR_IA32_FRED_SSP0, fred_ssp_canonical_val, fred_ssp_canonical= _val | 1, FRED, SHSTK), + MSR_TEST_CANONICAL(MSR_IA32_FRED_SSP1, FRED), + MSR_TEST(MSR_IA32_FRED_SSP1, fred_ssp_canonical_val, fred_ssp_canonical_= val | 2, FRED), + MSR_TEST_CANONICAL(MSR_IA32_FRED_SSP2, FRED), + MSR_TEST(MSR_IA32_FRED_SSP2, fred_ssp_canonical_val, fred_ssp_canonical_= val | 4, FRED), + MSR_TEST_CANONICAL(MSR_IA32_FRED_SSP3, FRED), + MSR_TEST(MSR_IA32_FRED_SSP3, fred_ssp_canonical_val, fred_ssp_canonical_= val | 7, FRED), + + MSR_TEST(MSR_IA32_FRED_STKLVLS, 0xe41be41be41be41b, 0, FRED), + + MSR_TEST_CANONICAL(MSR_IA32_FRED_CONFIG, FRED), + MSR_TEST(MSR_IA32_FRED_CONFIG, canonical_val, canonical_val | FRED_CONFI= G_RESERVED, FRED), }; =20 const struct kvm_x86_cpu_feature feat_none =3D X86_FEATURE_NONE; const struct kvm_x86_cpu_feature feat_lm =3D X86_FEATURE_LM; + const struct kvm_x86_cpu_feature feat_fred =3D X86_FEATURE_FRED; =20 /* * Create three vCPUs, but run them on the same task, to validate KVM's @@ -432,6 +472,14 @@ static void test_msrs(void) * immutable once the vCPU has been run. */ for (idx =3D 0; idx < ARRAY_SIZE(__msrs); idx++) { + /* + * Feature word 0x7:1:EAX used by FRED doesn't exist on some CPU + * models, simply skip clearing FRED feature bit. + */ + if (!memcmp(&msrs[idx].feature, &feat_fred, sizeof(feat_fred)) && + !kvm_cpu_has(X86_FEATURE_FRED)) + continue; + /* * Don't clear LM; selftests are 64-bit only, and KVM doesn't * honor LM=3D0 for MSRs that are supposed to exist if and only --=20 2.43.0 From nobody Fri Sep 25 13:16:55 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) (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 BADA54BEE57; Fri, 11 Sep 2026 21:44:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789163045; cv=none; b=DkAVwliNiOEUIsVZOgjtu7SAgzLYVw5fI7XxDUu2RI67llILLCWfQFwcpJiWLyYcTm46snhftlXwTa6UhPHB2pAJ3CSRWF9/b0PtlMx+QTDEuWt6JBNHGNZruUG2Tr3Wdx24q76tzAROkZotJY2h+wjiiZl64foD5fC9lKxTSbQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789163045; c=relaxed/simple; bh=LmGadgze0iyyl8KmfsawwtBrbsoXIrl6uQyMW4y3r3w=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=VCqDA/jbZlUhX9QZH7ey5hplgGCqIc69oEt6CWOwg4TALWE6NKMRpwRsVBYERVovjo1VBp4jNx43KQCK4FC4XJ6SPxwtpnuEAXonvT5bPklnfJStTeYYYYC8R79EK9We6D/4Osneh8FBvyzjApRZhsvUWWlF3/KlbHN8ovN5XjA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=Z9b2m6EZ; arc=none smtp.client-ip=192.198.163.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="Z9b2m6EZ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789163043; x=1820699043; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=LmGadgze0iyyl8KmfsawwtBrbsoXIrl6uQyMW4y3r3w=; b=Z9b2m6EZuym78oVOD8Om+0C0bzQaymYMQOi+CnkF0snD73YurPt8MLoO QjGOFk9RsDjS0HDjzns9dIhLk9uzyBQaTsJuUsysmzKH794Ftn9RnCtEc 4lo3Bhr5YAv7DrYYnUL8hb1oePisXh+Uln5EKNB47N3ddf12QjVyjuxNu KXf0vi7FlTEISyjxeHtbvFfAz3fvuU79FSKVPAyDXpBFwWtI3WiRFJn5w Y1/s3mPag/HOycV0vnTGcfczbFQHs13xtSgmmCp6BPA3EsC85d5YcTr5b GSNqj3NkggVJ5+ZT2PiXD/AgkGCvi6wSGTlYQ6+zkTBI8DhgozlugQvfv g==; X-CSE-ConnectionGUID: Bs34d6RqQkmpeU+iTaKcTA== X-CSE-MsgGUID: z80VRbzwQ1SFMMPlk/YUSQ== X-IronPort-AV: E=McAfee;i="6800,10657,11902"; a="88572951" X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="88572951" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Sep 2026 14:44:02 -0700 X-CSE-ConnectionGUID: okdgUtZUQJm5ZcdU0+n7zA== X-CSE-MsgGUID: IDGTdOTqTxa49fLmP4obww== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="272004440" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa007.jf.intel.com with ESMTP; 11 Sep 2026 14:44:01 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Paolo Bonzini , Sean Christopherson , Jonathan Corbet , Shuah Khan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Xin Li , Andy Lutomirski , Peter Zijlstra , Andrew Cooper , Tom Lendacky , Nikunj A Dadhania , Shivansh Dhiman , David Woodhouse , Chao Gao , Binbin Wu , Sohil Mehta , Zhao Liu , Yosry Ahmed , David Matlack , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v10 27/28] KVM: selftests: Add a new VM guest mode to run user level code Date: Fri, 11 Sep 2026 14:36:57 -0700 Message-ID: <20260911213659.2025974-28-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260911213659.2025974-1-sohil.mehta@intel.com> References: <20260911213659.2025974-1-sohil.mehta@intel.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 (Intel)" Add a new VM guest mode VM_MODE_PXXV48_4K_USER to set the user bit of guest page table entries, thus allow user level code to run in guests. Suggested-by: Sean Christopherson Signed-off-by: Xin Li (Intel) Signed-off-by: Sohil Mehta --- v10: - Treat as new patch (last posted in v2). --- tools/testing/selftests/kvm/include/kvm_util.h | 1 + tools/testing/selftests/kvm/lib/kvm_util.c | 5 ++++- tools/testing/selftests/kvm/lib/x86/processor.c | 16 ++++++++++++---- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing= /selftests/kvm/include/kvm_util.h index 5a7a455b5387..981adfcbd5fa 100644 --- a/tools/testing/selftests/kvm/include/kvm_util.h +++ b/tools/testing/selftests/kvm/include/kvm_util.h @@ -191,6 +191,7 @@ enum vm_guest_mode { VM_MODE_P40V48_16K, VM_MODE_P40V48_64K, VM_MODE_PXXVYY_4K, /* For 48-bit or 57-bit VA, depending on host support = */ + VM_MODE_PXXVYY_4K_USER, /* For 48bits VA but ANY bits PA with USER bit se= t */ VM_MODE_P47V64_4K, VM_MODE_P44V64_4K, VM_MODE_P36V48_4K, diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/sel= ftests/kvm/lib/kvm_util.c index 9ddc047d5c27..e79fddedaf39 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -210,6 +210,7 @@ const char *vm_guest_mode_string(u32 i) [VM_MODE_P40V48_16K] =3D "PA-bits:40, VA-bits:48, 16K pages", [VM_MODE_P40V48_64K] =3D "PA-bits:40, VA-bits:48, 64K pages", [VM_MODE_PXXVYY_4K] =3D "PA-bits:ANY, VA-bits:48 or 57, 4K pages", + [VM_MODE_PXXVYY_4K_USER]=3D "PA-bits:ANY, VA-bits:48, 4K user pages", [VM_MODE_P47V64_4K] =3D "PA-bits:47, VA-bits:64, 4K pages", [VM_MODE_P44V64_4K] =3D "PA-bits:44, VA-bits:64, 4K pages", [VM_MODE_P36V48_4K] =3D "PA-bits:36, VA-bits:48, 4K pages", @@ -246,6 +247,7 @@ const struct vm_guest_mode_params vm_guest_mode_params[= ] =3D { [VM_MODE_P40V48_16K] =3D { 40, 48, 0x4000, 14 }, [VM_MODE_P40V48_64K] =3D { 40, 48, 0x10000, 16 }, [VM_MODE_PXXVYY_4K] =3D { 0, 0, 0x1000, 12 }, + [VM_MODE_PXXVYY_4K_USER]=3D { 0, 0, 0x1000, 12 }, [VM_MODE_P47V64_4K] =3D { 47, 64, 0x1000, 12 }, [VM_MODE_P44V64_4K] =3D { 44, 64, 0x1000, 12 }, [VM_MODE_P36V48_4K] =3D { 36, 48, 0x1000, 12 }, @@ -337,6 +339,7 @@ struct kvm_vm *____vm_create(struct vm_shape shape) vm->mmu.pgtable_levels =3D 3; break; case VM_MODE_PXXVYY_4K: + case VM_MODE_PXXVYY_4K_USER: #ifdef __x86_64__ kvm_get_cpu_address_width(&vm->pa_bits, &vm->va_bits); kvm_init_vm_address_properties(vm); @@ -355,7 +358,7 @@ struct kvm_vm *____vm_create(struct vm_shape shape) vm->mmu.pgtable_levels =3D 4; } #else - TEST_FAIL("VM_MODE_PXXVYY_4K not supported on non-x86 platforms"); + TEST_FAIL("VM_MODE_PXXVYY_4K(_USER) not supported on non-x86 platforms"); #endif break; case VM_MODE_P47V64_4K: diff --git a/tools/testing/selftests/kvm/lib/x86/processor.c b/tools/testin= g/selftests/kvm/lib/x86/processor.c index d31fa81ea075..51d713c4c9de 100644 --- a/tools/testing/selftests/kvm/lib/x86/processor.c +++ b/tools/testing/selftests/kvm/lib/x86/processor.c @@ -167,6 +167,9 @@ bool kvm_is_tdp_enabled(void) static void virt_mmu_init(struct kvm_vm *vm, struct kvm_mmu *mmu, struct pte_masks *pte_masks) { + TEST_ASSERT(vm->mode =3D=3D VM_MODE_PXXVYY_4K || vm->mode =3D=3D VM_MODE_= PXXVYY_4K_USER, + "Unknown or unsupported guest mode: 0x%x", vm->mode); + /* If needed, create the top-level page table. */ if (!mmu->pgd_created) { mmu->pgd =3D vm_alloc_page_table(vm); @@ -181,7 +184,7 @@ static void virt_mmu_init(struct kvm_vm *vm, struct kvm= _mmu *mmu, =20 void virt_arch_pgd_alloc(struct kvm_vm *vm) { - TEST_ASSERT(vm->mode =3D=3D VM_MODE_PXXVYY_4K, + TEST_ASSERT(vm->mode =3D=3D VM_MODE_PXXVYY_4K || vm->mode =3D=3D VM_MODE_= PXXVYY_4K_USER, "Unknown or unsupported guest mode: 0x%x", vm->mode); =20 struct pte_masks pte_masks =3D (struct pte_masks){ @@ -239,6 +242,8 @@ static u64 *virt_create_upper_pte(struct kvm_vm *vm, *pte =3D PTE_PRESENT_MASK(mmu) | PTE_READABLE_MASK(mmu) | PTE_WRITABLE_MASK(mmu) | PTE_EXECUTABLE_MASK(mmu) | PTE_ALWAYS_SET_MASK(mmu); + if (vm->mode =3D=3D VM_MODE_PXXVYY_4K_USER) + *pte |=3D PTE_USER_MASK(mmu); if (current_level =3D=3D target_level) *pte |=3D PTE_HUGE_MASK(mmu) | (gpa & PHYSICAL_PAGE_MASK); else @@ -266,7 +271,7 @@ void __virt_pg_map(struct kvm_vm *vm, struct kvm_mmu *m= mu, gva_t gva, u64 *pte =3D &mmu->pgd; int current_level; =20 - TEST_ASSERT(vm->mode =3D=3D VM_MODE_PXXVYY_4K, + TEST_ASSERT(vm->mode =3D=3D VM_MODE_PXXVYY_4K || vm->mode =3D=3D VM_MODE_= PXXVYY_4K_USER, "Unknown or unsupported guest mode: 0x%x", vm->mode); =20 TEST_ASSERT((gva % pg_size) =3D=3D 0, @@ -316,6 +321,9 @@ void __virt_pg_map(struct kvm_vm *vm, struct kvm_mmu *m= mu, gva_t gva, *pte |=3D PTE_C_BIT_MASK(mmu); else *pte |=3D PTE_S_BIT_MASK(mmu); + + if (vm->mode =3D=3D VM_MODE_PXXVYY_4K_USER) + *pte |=3D PTE_USER_MASK(mmu); } =20 void virt_arch_pg_map(struct kvm_vm *vm, gva_t gva, gpa_t gpa) @@ -372,7 +380,7 @@ static u64 *__vm_get_page_table_entry(struct kvm_vm *vm, TEST_ASSERT(*level >=3D PG_LEVEL_NONE && *level <=3D mmu->pgtable_levels, "Invalid PG_LEVEL_* '%d'", *level); =20 - TEST_ASSERT(vm->mode =3D=3D VM_MODE_PXXVYY_4K, + TEST_ASSERT(vm->mode =3D=3D VM_MODE_PXXVYY_4K || vm->mode =3D=3D VM_MODE_= PXXVYY_4K_USER, "Unknown or unsupported guest mode: 0x%x", vm->mode); TEST_ASSERT(sparsebit_is_set(vm->vpages_valid, (gva >> vm->page_shift)), "Invalid virtual address, gva: 0x%lx", gva); @@ -645,7 +653,7 @@ static void vcpu_init_sregs(struct kvm_vm *vm, struct k= vm_vcpu *vcpu) { struct kvm_sregs sregs; =20 - TEST_ASSERT(vm->mode =3D=3D VM_MODE_PXXVYY_4K, + TEST_ASSERT(vm->mode =3D=3D VM_MODE_PXXVYY_4K || vm->mode =3D=3D VM_MODE_= PXXVYY_4K_USER, "Unknown or unsupported guest mode: 0x%x", vm->mode); =20 /* Set mode specific system register values. */ --=20 2.43.0 From nobody Fri Sep 25 13:16:55 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) (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 A2E5B499180; Fri, 11 Sep 2026 21:44:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789163055; cv=none; b=E51LMIBN+jRdiTuudistMqro3M7VkEgGqqERHJLtA/vAxIeFbLxu4wzmqP7VJsL0BzZA+DwcJ6SOAeeRKzg88kEYTl7cicOQITihZMv9ayMhuJhmA/3TnB2YQiAOS1jldnYwZqILas6PsPdi10sd23eJo0Jwr9ZgnTXwKFmdkz0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789163055; c=relaxed/simple; bh=+1Jw4fuAgngN372/rAoxqz0Tgs9H4oIDq5miF7p/D5I=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=j+UbOJ8LiC6vK+iEn1sU++2Tjy6Oq9wslh1VsJ64C3OOg0O9Nw/Bp2UN+nlmZn2xO2aGM0UdWy26ZEjG8eiW/AXNKuRjjnq5RW6UfB/P/ThJbNE6gGluHvP8N/P5FfCCZFRBPuj6mmyFDNDZCtlklr1ToKtN7ho4REKVDQRsOlA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=X9u3SKaE; arc=none smtp.client-ip=192.198.163.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="X9u3SKaE" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789163054; x=1820699054; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=+1Jw4fuAgngN372/rAoxqz0Tgs9H4oIDq5miF7p/D5I=; b=X9u3SKaEkSGo6gQNlmsOz/u7BP4VWLQf4nCzXNBcI0fiStx7SUaw9z77 Ez49k/ZgeF7ZMr+qs68Rinp6cX5Pnj7LmZD+AhAwCJ5hBLf+5YXH80SMb SjDbn1Y1ciK96wm2VWecdc/UGzzVqjYXXb4vFadtArkE9BuBvamlK/9HY 6hWfkg8hqKqHcDbRAQEB4f/r6RBUFJED2bLB8mmARP4jLLJ47+FPLEdyq bEZvjNb7u8S1qxPDKT3NjAzgYHhR2qbAzfcmKbqLF5H197eqbyr9dtYs2 AIizzdQvPyvDKLEU1ml29IUE2Zajwba0IfAyzV7QC/x9Iqt4XBzL4WOHb w==; X-CSE-ConnectionGUID: x9rtjajvQnigSshsvJVZdQ== X-CSE-MsgGUID: 2/Xfyi9ERAOJayYrhKk9rw== X-IronPort-AV: E=McAfee;i="6800,10657,11902"; a="88572965" X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="88572965" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Sep 2026 14:44:13 -0700 X-CSE-ConnectionGUID: r2ywHAtgS5iYi8bKN5Xb2A== X-CSE-MsgGUID: 9dB1DladTp2MmzWCr17SEw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,98,1787036400"; d="scan'208";a="272004480" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa007.jf.intel.com with ESMTP; 11 Sep 2026 14:44:12 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Paolo Bonzini , Sean Christopherson , Jonathan Corbet , Shuah Khan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Xin Li , Andy Lutomirski , Peter Zijlstra , Andrew Cooper , Tom Lendacky , Nikunj A Dadhania , Shivansh Dhiman , David Woodhouse , Chao Gao , Binbin Wu , Sohil Mehta , Zhao Liu , Yosry Ahmed , David Matlack , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v10 28/28] KVM: selftests: Add fred exception tests Date: Fri, 11 Sep 2026 14:36:58 -0700 Message-ID: <20260911213659.2025974-29-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260911213659.2025974-1-sohil.mehta@intel.com> References: <20260911213659.2025974-1-sohil.mehta@intel.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 (Intel)" Add tests for FRED event data and VMX nested-exception. FRED is designed to save a complete event context in its stack frame, e.g., FRED saves the faulting linear address of a #PF into a 64-bit event data field defined in FRED stack frame. As such, FRED VMX adds event data handling during VMX transitions. Besides, FRED introduces event stack levels to dispatch an event handler onto a stack based on current stack level and stack levels defined in IA32_FRED_STKLVLS MSR for each exception vector. VMX nested-exception support ensures a correct event stack level is chosen when a VM entry injects a nested exception, which is regarded as occurred in ring 0. To fully test the underlying FRED VMX code, this test should be run one more round with EPT disabled to inject page faults as nested exceptions. Originally-by: Shan Kang Signed-off-by: Xin Li (Intel) Signed-off-by: Sohil Mehta --- v10: - Treat as new patch (last posted in v2). --- tools/testing/selftests/kvm/Makefile.kvm | 1 + .../selftests/kvm/include/x86/processor.h | 33 ++ tools/testing/selftests/kvm/x86/fred_test.c | 291 ++++++++++++++++++ 3 files changed, 325 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86/fred_test.c diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selft= ests/kvm/Makefile.kvm index 96bab7002d39..73aed018f4a3 100644 --- a/tools/testing/selftests/kvm/Makefile.kvm +++ b/tools/testing/selftests/kvm/Makefile.kvm @@ -78,6 +78,7 @@ TEST_GEN_PROGS_x86 +=3D x86/feature_msrs_test TEST_GEN_PROGS_x86 +=3D x86/evmcs_smm_controls_test TEST_GEN_PROGS_x86 +=3D x86/exit_on_emulation_failure_test TEST_GEN_PROGS_x86 +=3D x86/fastops_test +TEST_GEN_PROGS_x86 +=3D x86/fred_test TEST_GEN_PROGS_x86 +=3D x86/fix_hypercall_test TEST_GEN_PROGS_x86 +=3D x86/hwcr_msr_test TEST_GEN_PROGS_x86 +=3D x86/hyperv_clock diff --git a/tools/testing/selftests/kvm/include/x86/processor.h b/tools/te= sting/selftests/kvm/include/x86/processor.h index 916646cb4d89..988c45e32689 100644 --- a/tools/testing/selftests/kvm/include/x86/processor.h +++ b/tools/testing/selftests/kvm/include/x86/processor.h @@ -79,6 +79,7 @@ const char *ex_str(int vector); #define X86_CR4_SMEP (1ul << 20) #define X86_CR4_SMAP (1ul << 21) #define X86_CR4_PKE (1ul << 22) +#define X86_CR4_FRED (1ul << 32) =20 struct xstate_header { u64 xstate_bv; @@ -1646,4 +1647,36 @@ u64 *tdp_get_pte(struct kvm_vm *vm, u64 l2_gpa); =20 bool sys_clocksource_is_based_on_tsc(void); =20 +/* + * FRED related data structures and functions + */ + +#define FRED_SSX_NMI BIT_ULL(18) + +struct fred_stack { + u64 r15; + u64 r14; + u64 r13; + u64 r12; + u64 bp; + u64 bx; + u64 r11; + u64 r10; + u64 r9; + u64 r8; + u64 ax; + u64 cx; + u64 dx; + u64 si; + u64 di; + u64 error_code; + u64 ip; + u64 csx; + u64 flags; + u64 sp; + u64 ssx; + u64 event_data; + u64 reserved; +}; + #endif /* SELFTEST_KVM_PROCESSOR_H */ diff --git a/tools/testing/selftests/kvm/x86/fred_test.c b/tools/testing/se= lftests/kvm/x86/fred_test.c new file mode 100644 index 000000000000..c7d08e5253b9 --- /dev/null +++ b/tools/testing/selftests/kvm/x86/fred_test.c @@ -0,0 +1,291 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * FRED nested exception tests + * + * Copyright (C) 2023, Intel, Inc. + */ +#define _GNU_SOURCE /* for program_invocation_short_name */ +#include +#include +#include +#include +#include +#include + +#include "apic.h" +#include "kvm_util.h" +#include "test_util.h" +#include "guest_modes.h" +#include "processor.h" + +#define IRQ_VECTOR 0xAA + +#define FRED_STKLVL(v,l) (_AT(unsigned long, l) << (2 * (v))) +#define FRED_CONFIG_ENTRYPOINT(p) _AT(unsigned long, (p)) + +/* This address is already mapped in guest page table. */ +#define FRED_VALID_RSP 0x8000 + +/* + * The following addresses are not yet mapped in both EPT and guest page + * tables at the beginning. As a result, it causes an EPT violation VM + * exit with an original guest #PF to access any of them for the first + * time. + * + * Use these addresses as guest FRED RSP0 to generate nested #PFs to test + * if event data are properly virtualized. + */ +static unsigned long fred_invalid_rsp[4] =3D { + 0x0, + 0xf0000000, + 0xe0000000, + 0xd0000000, +}; + +extern char asm_user_nop[]; +extern char asm_user_ud[]; +extern char asm_done_fault[]; + +extern void asm_test_fault(int test); + +/* + * user level code for triggering faults. + */ +asm(".pushsection .text\n" + ".align 4096\n" + + ".type asm_user_nop, @function\n" + "asm_user_nop:\n" + "1: .byte 0x90\n" + "jmp 1b\n" + + ".org asm_user_nop + 16, 0xcc\n" + ".type asm_user_ud, @function\n" + "asm_user_ud:\n" + /* Trigger a #UD */ + "ud2\n" + + ".align 4096, 0xcc\n" + ".popsection"); + +/* Send current stack level and #PF address */ +#define GUEST_SYNC_CSL_FA(__stage, __pf_address) \ + GUEST_SYNC_ARGS(__stage, __pf_address, 0, 0, 0) + +void fred_entry_from_user(struct fred_stack *stack) +{ + u32 current_stack_level =3D rdmsr(MSR_IA32_FRED_CONFIG) & 0x3; + + GUEST_SYNC_CSL_FA(current_stack_level, stack->event_data); + + /* Do NOT go back to user level, continue the next test instead */ + stack->ssx =3D 0x18; + stack->csx =3D 0x10; + stack->ip =3D (u64)&asm_done_fault; +} + +void fred_entry_from_kernel(struct fred_stack *stack) +{ + /* + * Keep NMI blocked to delay the delivery of the next NMI until + * returning to user level. + * */ + stack->ssx &=3D ~FRED_SSX_NMI; +} + +#define PUSH_REGS \ + "push %rdi\n" \ + "push %rsi\n" \ + "push %rdx\n" \ + "push %rcx\n" \ + "push %rax\n" \ + "push %r8\n" \ + "push %r9\n" \ + "push %r10\n" \ + "push %r11\n" \ + "push %rbx\n" \ + "push %rbp\n" \ + "push %r12\n" \ + "push %r13\n" \ + "push %r14\n" \ + "push %r15\n" + +#define POP_REGS \ + "pop %r15\n" \ + "pop %r14\n" \ + "pop %r13\n" \ + "pop %r12\n" \ + "pop %rbp\n" \ + "pop %rbx\n" \ + "pop %r11\n" \ + "pop %r10\n" \ + "pop %r9\n" \ + "pop %r8\n" \ + "pop %rax\n" \ + "pop %rcx\n" \ + "pop %rdx\n" \ + "pop %rsi\n" \ + "pop %rdi\n" + +/* + * FRED entry points. + */ +asm(".pushsection .text\n" + ".type asm_fred_entrypoint_user, @function\n" + ".align 4096\n" + "asm_fred_entrypoint_user:\n" + PUSH_REGS + "movq %rsp, %rdi\n" + "call fred_entry_from_user\n" + POP_REGS + /* Do NOT go back to user level, continue the next test instead */ + ".byte 0xf2,0x0f,0x01,0xca\n" /* ERETS */ + + ".org asm_fred_entrypoint_user + 256, 0xcc\n" + ".type asm_fred_entrypoint_kernel, @function\n" + "asm_fred_entrypoint_kernel:\n" + PUSH_REGS + "movq %rsp, %rdi\n" + "call fred_entry_from_kernel\n" + POP_REGS + ".byte 0xf2,0x0f,0x01,0xca\n" /* ERETS */ + ".align 4096, 0xcc\n" + ".popsection"); + +extern char asm_fred_entrypoint_user[]; + +/* + * Prepare a FRED stack frame for ERETU to return to user level code, + * nop or ud2. + * + * Because FRED RSP0 is deliberately not mapped in guest page table, + * the delivery of interrupt/NMI or #UD from ring 3 causes a nested + * #PF, which is then delivered on FRED RSPx (x is 1, 2 or 3, + * determinated by MSR FRED_STKLVL[PF_VECTOR]). + */ +asm(".pushsection .text\n" + ".type asm_test_fault, @function\n" + ".align 4096\n" + "asm_test_fault:\n" + "endbr64\n" + "push %rbp\n" + "mov %rsp, %rbp\n" + "and $(~0x3f), %rsp\n" + "push $0\n" + "push $0\n" + "mov $0x2b, %rax\n" + /* Unblock NMI */ + "bts $18, %rax\n" + /* Set long mode bit */ + "bts $57, %rax\n" + "push %rax\n" + /* No stack required for the FRED user level test code */ + "push $0\n" + "pushf\n" + "pop %rax\n" + /* Allow external interrupts */ + "bts $9, %rax\n" + "push %rax\n" + "mov $0x33, %rax\n" + "push %rax\n" + "cmp $0, %edi\n" + "jne 1f\n" + "lea asm_user_nop(%rip), %rax\n" + "jmp 2f\n" + "1: lea asm_user_ud(%rip), %rax\n" + "2: push %rax\n" + "push $0\n" + /* ERETU to user level code to allow event delivery immediately */ + ".byte 0xf3,0x0f,0x01,0xca\n" + "asm_done_fault:\n" + "mov %rbp, %rsp\n" + "pop %rbp\n" + "ret\n" + ".align 4096, 0xcc\n" + ".popsection"); + +/* + * To fully test the underlying FRED VMX code, this test should be run one + * more round with EPT disabled to inject page faults as nested exceptions. + */ +static void guest_code(void) +{ + wrmsr(MSR_IA32_FRED_CONFIG, + FRED_CONFIG_ENTRYPOINT(asm_fred_entrypoint_user)); + + wrmsr(MSR_IA32_FRED_RSP1, FRED_VALID_RSP); + wrmsr(MSR_IA32_FRED_RSP2, FRED_VALID_RSP); + wrmsr(MSR_IA32_FRED_RSP3, FRED_VALID_RSP); + + /* Enable FRED */ + set_cr4(get_cr4() | X86_CR4_FRED); + + x2apic_enable(); + + wrmsr(MSR_IA32_FRED_STKLVLS, FRED_STKLVL(PF_VECTOR, 1)); + wrmsr(MSR_IA32_FRED_RSP0, fred_invalid_rsp[1]); + /* 1: ud2 to generate #UD */ + asm_test_fault(1); + + wrmsr(MSR_IA32_FRED_STKLVLS, FRED_STKLVL(PF_VECTOR, 2)); + wrmsr(MSR_IA32_FRED_RSP0, fred_invalid_rsp[2]); + asm volatile("cli"); + /* Create a pending interrupt on current vCPU */ + x2apic_write_reg(APIC_ICR, APIC_DEST_SELF | APIC_INT_ASSERT | + APIC_DM_FIXED | IRQ_VECTOR); + /* Return to ring 3 */ + asm_test_fault(0); + x2apic_write_reg(APIC_EOI, 0); + + wrmsr(MSR_IA32_FRED_STKLVLS, FRED_STKLVL(PF_VECTOR, 3)); + wrmsr(MSR_IA32_FRED_RSP0, fred_invalid_rsp[3]); + /* + * The first NMI is just to have NMI blocked in ring 0, because + * fred_entry_from_kernel() deliberately clears the NMI bit in + * FRED stack frame. + */ + x2apic_write_reg(APIC_ICR, APIC_DEST_SELF | APIC_INT_ASSERT | + APIC_DM_NMI | NMI_VECTOR); + /* The second NMI will be delivered after returning to ring 3 */ + x2apic_write_reg(APIC_ICR, APIC_DEST_SELF | APIC_INT_ASSERT | + APIC_DM_NMI | NMI_VECTOR); + /* Return to ring 3 */ + asm_test_fault(0); + + GUEST_DONE(); +} + +int main(int argc, char *argv[]) +{ + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + struct ucall uc; + uint64_t expected_current_stack_level =3D 1; + + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_FRED)); + + vm =3D __vm_create_with_vcpus(VM_SHAPE(VM_MODE_PXXVYY_4K_USER), 1, 0, + guest_code, &vcpu); + + while (true) { + uint64_t r; + + vcpu_run(vcpu); + + r =3D get_ucall(vcpu, &uc); + + if (r =3D=3D UCALL_DONE) + break; + + if (r =3D=3D UCALL_SYNC) { + TEST_ASSERT((uc.args[1] =3D=3D expected_current_stack_level) && + (uc.args[2] =3D=3D fred_invalid_rsp[expected_current_stack_level] = - 8), + "Incorrect stack level %lx and #PF address %lx\n", + uc.args[1], uc.args[2]); + expected_current_stack_level++; + } + } + + kvm_vm_free(vm); + return 0; +} --=20 2.43.0