From: Sohil Mehta <sohil.mehta@intel.com>
To: kvm@vger.kernel.org, x86@kernel.org
Cc: Paolo Bonzini <pbonzini@redhat.com>,
Sean Christopherson <seanjc@google.com>,
Jonathan Corbet <corbet@lwn.net>,
Shuah Khan <skhan@linuxfoundation.org>,
Thomas Gleixner <tglx@kernel.org>, Ingo Molnar <mingo@redhat.com>,
Borislav Petkov <bp@alien8.de>,
Dave Hansen <dave.hansen@linux.intel.com>,
"H . Peter Anvin" <hpa@zytor.com>, Xin Li <xin@zytor.com>,
Andy Lutomirski <luto@kernel.org>,
Peter Zijlstra <peterz@infradead.org>,
Andrew Cooper <andrew.cooper3@citrix.com>,
Tom Lendacky <thomas.lendacky@amd.com>,
Nikunj A Dadhania <nikunj@amd.com>,
Shivansh Dhiman <shivansh.dhiman@amd.com>,
David Woodhouse <dwmw@amazon.co.uk>,
Chao Gao <chao.gao@intel.com>,
Binbin Wu <binbin.wu@linux.intel.com>,
Sohil Mehta <sohil.mehta@intel.com>,
Zhao Liu <zhao1.liu@intel.com>, Yosry Ahmed <yosry@kernel.org>,
David Matlack <dmatlack@google.com>,
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 [thread overview]
Message-ID: <20260911213659.2025974-11-sohil.mehta@intel.com> (raw)
In-Reply-To: <20260911213659.2025974-1-sohil.mehta@intel.com>
From: "Xin Li (Intel)" <xin@zytor.com>
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) <xin@zytor.com>
Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
Reviewed-by: Chao Gao <chao.gao@intel.com>
---
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_host.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;
};
struct kvm_lpage_info {
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.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 level */
+#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[] = {
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 index, 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 index, u64 data,
if (index != 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 = 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 = FRED_CONFIG_RESERVED;
+ break;
+ case MSR_IA32_FRED_RSP0 ... MSR_IA32_FRED_RSP3:
+ reserved_bits = GENMASK_ULL(5, 0);
+ break;
+ case MSR_IA32_FRED_SSP1 ... MSR_IA32_FRED_SSP3:
+ reserved_bits = 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;
}
msr.data = data;
@@ -841,10 +890,19 @@ static int __kvm_get_msr(struct kvm_vcpu *vcpu, u32 index, 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;
}
msr.index = 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 != MSR_IA32_FRED_SSP0);
+ vcpu->arch.fred_ssp0_fallback = 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 != MSR_IA32_FRED_SSP0);
+ msr_info->data = 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 vcpu_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
static void grow_ple_window(struct kvm_vcpu *vcpu)
@@ -2140,6 +2152,27 @@ int vmx_get_feature_msr(u32 msr, u64 *data)
}
}
+#ifdef CONFIG_X86_64
+static const u32 fred_msr_vmcs_fields[] = {
+ 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 ==
+ 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_data *msr_info)
case MSR_KERNEL_GS_BASE:
msr_info->data = vmx_read_guest_kernel_gs_base(vmx);
break;
+ case MSR_IA32_FRED_RSP0:
+ msr_info->data = vmx_read_guest_fred_rsp0(vmx);
+ break;
+ case MSR_IA32_FRED_RSP1 ... MSR_IA32_FRED_CONFIG:
+ msr_info->data = 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_data *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))
--
2.43.0
next prev parent reply other threads:[~2026-09-11 21:41 UTC|newest]
Thread overview: 51+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-11 21:36 [PATCH v10 00/28] KVM: Enable FRED support with KVM VMX Sohil Mehta
2026-09-11 21:36 ` [PATCH v10 01/28] KVM: VMX: Enable support for secondary VM exit controls Sohil Mehta
2026-09-11 21:36 ` [PATCH v10 02/28] KVM: VMX: Initialize VM entry/exit FRED controls in vmcs_config Sohil Mehta
2026-09-11 22:00 ` sashiko-bot
2026-09-11 21:36 ` [PATCH v10 03/28] KVM: VMX: Disable FRED if FRED consistency checks fail Sohil Mehta
2026-09-11 22:08 ` sashiko-bot
2026-09-11 21:36 ` [PATCH v10 04/28] x86/cea: Prefix event stack names with ESTACK_ Sohil Mehta
2026-09-11 21:36 ` [PATCH v10 05/28] x86/cea: Use array indexing to simplify exception stack access Sohil Mehta
2026-09-11 21:57 ` sashiko-bot
2026-09-11 21:36 ` [PATCH v10 06/28] x86/fred: Export this_cpu_fred_rsp() for KVM usage Sohil Mehta
2026-09-11 21:36 ` [PATCH v10 07/28] KVM: VMX: Initialize VMCS FRED fields Sohil Mehta
2026-09-11 22:10 ` sashiko-bot
2026-09-11 21:36 ` [PATCH v10 08/28] KVM: VMX: Set FRED MSR intercepts Sohil Mehta
2026-09-11 21:36 ` [PATCH v10 09/28] KVM: VMX: Save/restore guest FRED RSP0 Sohil Mehta
2026-09-14 7:04 ` Binbin Wu
2026-09-14 16:14 ` Edgecombe, Rick P
2026-09-15 8:43 ` Binbin Wu
2026-09-11 21:36 ` Sohil Mehta [this message]
2026-09-11 21:36 ` [PATCH v10 11/28] KVM: x86: Add a helper to detect if FRED is enabled for a vCPU Sohil Mehta
2026-09-11 21:36 ` [PATCH v10 12/28] KVM: x86: Add a new save/restore flag for FRED metadata Sohil Mehta
2026-09-11 21:36 ` [PATCH v10 13/28] KVM: VMX: Virtualize FRED nested exception tracking Sohil Mehta
2026-09-11 22:09 ` sashiko-bot
2026-09-11 21:36 ` [PATCH v10 14/28] KVM: VMX: Virtualize FRED event_data Sohil Mehta
2026-09-11 21:36 ` [PATCH v10 15/28] KVM: x86: Include CR4.FRED in the emulator CR4 write mask Sohil Mehta
2026-09-11 22:14 ` sashiko-bot
2026-09-11 21:36 ` [PATCH v10 16/28] KVM: x86: Mark CR4.FRED as not reserved Sohil Mehta
2026-09-11 22:14 ` sashiko-bot
2026-09-11 21:36 ` [PATCH v10 17/28] KVM: x86: Handle CR4.FRED when emulating RSM Sohil Mehta
2026-09-11 22:15 ` sashiko-bot
2026-09-11 21:36 ` [PATCH v10 18/28] KVM: VMX: Dump FRED context in dump_vmcs() Sohil Mehta
2026-09-11 22:11 ` sashiko-bot
2026-09-11 21:36 ` [PATCH v10 19/28] KVM: x86: Advertise support for FRED Sohil Mehta
2026-09-11 21:36 ` [PATCH v10 20/28] KVM: nVMX: Enable support for secondary VM exit controls Sohil Mehta
2026-09-11 21:36 ` [PATCH v10 21/28] KVM: nVMX: Handle FRED VMCS fields in nested VMX context Sohil Mehta
2026-09-11 22:34 ` sashiko-bot
2026-09-11 21:36 ` [PATCH v10 22/28] KVM: nVMX: Restrict event data VMCS fields to FRED-supported hosts Sohil Mehta
2026-09-11 22:20 ` sashiko-bot
2026-09-11 21:36 ` [PATCH v10 23/28] KVM: nVMX: Shadow ORIGINAL_EVENT_DATA and INJECTED_EVENT_DATA fields Sohil Mehta
2026-09-11 21:36 ` [PATCH v10 24/28] KVM: nVMX: Validate FRED-related VMCS fields Sohil Mehta
2026-09-11 22:29 ` sashiko-bot
2026-09-11 21:36 ` [PATCH v10 25/28] KVM: nVMX: Enable VMX FRED controls Sohil Mehta
2026-09-11 22:37 ` sashiko-bot
2026-09-11 21:36 ` [PATCH v10 26/28] KVM: selftests: Add FRED MSRs to msrs_test Sohil Mehta
2026-09-11 21:36 ` [PATCH v10 27/28] KVM: selftests: Add a new VM guest mode to run user level code Sohil Mehta
2026-09-11 21:36 ` [PATCH v10 28/28] KVM: selftests: Add fred exception tests Sohil Mehta
2026-09-11 22:32 ` sashiko-bot
2026-09-15 6:03 ` [PATCH v10 00/28] KVM: Enable FRED support with KVM VMX Xin Li
2026-09-15 10:00 ` [EXTERNAL] " David Woodhouse
2026-09-24 11:14 ` Shivansh Dhiman
2026-09-24 14:13 ` David Woodhouse
2026-09-25 12:06 ` Shivansh Dhiman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260911213659.2025974-11-sohil.mehta@intel.com \
--to=sohil.mehta@intel.com \
--cc=andrew.cooper3@citrix.com \
--cc=binbin.wu@linux.intel.com \
--cc=bp@alien8.de \
--cc=chao.gao@intel.com \
--cc=corbet@lwn.net \
--cc=dave.hansen@linux.intel.com \
--cc=dmatlack@google.com \
--cc=dwmw@amazon.co.uk \
--cc=hpa@zytor.com \
--cc=kvm@vger.kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=luto@kernel.org \
--cc=mingo@redhat.com \
--cc=nikunj@amd.com \
--cc=pbonzini@redhat.com \
--cc=peterz@infradead.org \
--cc=seanjc@google.com \
--cc=shivansh.dhiman@amd.com \
--cc=skhan@linuxfoundation.org \
--cc=tglx@kernel.org \
--cc=thomas.lendacky@amd.com \
--cc=x86@kernel.org \
--cc=xin@zytor.com \
--cc=yosry@kernel.org \
--cc=zhao1.liu@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.