From: Xin Li <xin3.li@intel.com>
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 <xin3.li@intel.com>
Signed-off-by: Xin Li (Intel) <xin@zytor.com>
Tested-by: Shan Kang <shan.kang@intel.com>
Tested-by: Xuelian Guo <xuelian.guo@intel.com>
---
Change in v5:
* Add TB from Xuelian Guo.
Change in v4:
* Initialize host SSP[1-3] to 0s in vmx_set_constant_host_state()
because Linux doesn't support kernel shadow stacks (Chao Gao).
Change in v3:
* Use structure kvm_host_values to keep host fred config & stack levels
(Sean Christopherson).
Changes in v2:
* Use kvm_cpu_cap_has() instead of cpu_feature_enabled() to decouple
KVM's capability to virtualize a feature and host's enabling of a
feature (Chao Gao).
* Move guest FRED state init into __vmx_vcpu_reset() (Chao Gao).
---
arch/x86/include/asm/vmx.h | 32 ++++++++++++++++++++++++++++++++
arch/x86/kvm/vmx/vmx.c | 36 ++++++++++++++++++++++++++++++++++++
arch/x86/kvm/x86.h | 3 +++
3 files changed, 71 insertions(+)
diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
index dd79d027ea70..6f8b8947c60c 100644
--- a/arch/x86/include/asm/vmx.h
+++ b/arch/x86/include/asm/vmx.h
@@ -293,12 +293,44 @@ enum vmcs_field {
GUEST_BNDCFGS_HIGH = 0x00002813,
GUEST_IA32_RTIT_CTL = 0x00002814,
GUEST_IA32_RTIT_CTL_HIGH = 0x00002815,
+ GUEST_IA32_FRED_CONFIG = 0x0000281a,
+ GUEST_IA32_FRED_CONFIG_HIGH = 0x0000281b,
+ GUEST_IA32_FRED_RSP1 = 0x0000281c,
+ GUEST_IA32_FRED_RSP1_HIGH = 0x0000281d,
+ GUEST_IA32_FRED_RSP2 = 0x0000281e,
+ GUEST_IA32_FRED_RSP2_HIGH = 0x0000281f,
+ GUEST_IA32_FRED_RSP3 = 0x00002820,
+ GUEST_IA32_FRED_RSP3_HIGH = 0x00002821,
+ GUEST_IA32_FRED_STKLVLS = 0x00002822,
+ GUEST_IA32_FRED_STKLVLS_HIGH = 0x00002823,
+ GUEST_IA32_FRED_SSP1 = 0x00002824,
+ GUEST_IA32_FRED_SSP1_HIGH = 0x00002825,
+ GUEST_IA32_FRED_SSP2 = 0x00002826,
+ GUEST_IA32_FRED_SSP2_HIGH = 0x00002827,
+ GUEST_IA32_FRED_SSP3 = 0x00002828,
+ GUEST_IA32_FRED_SSP3_HIGH = 0x00002829,
HOST_IA32_PAT = 0x00002c00,
HOST_IA32_PAT_HIGH = 0x00002c01,
HOST_IA32_EFER = 0x00002c02,
HOST_IA32_EFER_HIGH = 0x00002c03,
HOST_IA32_PERF_GLOBAL_CTRL = 0x00002c04,
HOST_IA32_PERF_GLOBAL_CTRL_HIGH = 0x00002c05,
+ HOST_IA32_FRED_CONFIG = 0x00002c08,
+ HOST_IA32_FRED_CONFIG_HIGH = 0x00002c09,
+ HOST_IA32_FRED_RSP1 = 0x00002c0a,
+ HOST_IA32_FRED_RSP1_HIGH = 0x00002c0b,
+ HOST_IA32_FRED_RSP2 = 0x00002c0c,
+ HOST_IA32_FRED_RSP2_HIGH = 0x00002c0d,
+ HOST_IA32_FRED_RSP3 = 0x00002c0e,
+ HOST_IA32_FRED_RSP3_HIGH = 0x00002c0f,
+ HOST_IA32_FRED_STKLVLS = 0x00002c10,
+ HOST_IA32_FRED_STKLVLS_HIGH = 0x00002c11,
+ HOST_IA32_FRED_SSP1 = 0x00002c12,
+ HOST_IA32_FRED_SSP1_HIGH = 0x00002c13,
+ HOST_IA32_FRED_SSP2 = 0x00002c14,
+ HOST_IA32_FRED_SSP2_HIGH = 0x00002c15,
+ HOST_IA32_FRED_SSP3 = 0x00002c16,
+ HOST_IA32_FRED_SSP3_HIGH = 0x00002c17,
PIN_BASED_VM_EXEC_CONTROL = 0x00004000,
CPU_BASED_VM_EXEC_CONTROL = 0x00004002,
EXCEPTION_BITMAP = 0x00004004,
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index fcfa99160018..c8b5359123bf 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -1459,6 +1459,15 @@ void vmx_vcpu_load_vmcs(struct kvm_vcpu *vcpu, int cpu)
(unsigned long)(cpu_entry_stack(cpu) + 1));
}
+ /* Per-CPU FRED MSRs */
+ if (kvm_cpu_cap_has(X86_FEATURE_FRED)) {
+#ifdef CONFIG_X86_64
+ vmcs_write64(HOST_IA32_FRED_RSP1, __this_cpu_ist_top_va(ESTACK_DB));
+ vmcs_write64(HOST_IA32_FRED_RSP2, __this_cpu_ist_top_va(ESTACK_NMI));
+ vmcs_write64(HOST_IA32_FRED_RSP3, __this_cpu_ist_top_va(ESTACK_DF));
+#endif
+ }
+
vmx->loaded_vmcs->cpu = cpu;
}
}
@@ -4330,6 +4339,17 @@ void vmx_set_constant_host_state(struct vcpu_vmx *vmx)
*/
vmcs_write16(HOST_DS_SELECTOR, 0);
vmcs_write16(HOST_ES_SELECTOR, 0);
+
+ if (kvm_cpu_cap_has(X86_FEATURE_FRED)) {
+ /* FRED CONFIG and STKLVLS are the same on all CPUs */
+ vmcs_write64(HOST_IA32_FRED_CONFIG, kvm_host.fred_config);
+ vmcs_write64(HOST_IA32_FRED_STKLVLS, kvm_host.fred_stklvls);
+
+ /* Linux doesn't support kernel shadow stacks, thus SSPs are 0s */
+ vmcs_write64(HOST_IA32_FRED_SSP1, 0);
+ vmcs_write64(HOST_IA32_FRED_SSP2, 0);
+ vmcs_write64(HOST_IA32_FRED_SSP3, 0);
+ }
#else
vmcs_write16(HOST_DS_SELECTOR, __KERNEL_DS); /* 22.2.4 */
vmcs_write16(HOST_ES_SELECTOR, __KERNEL_DS); /* 22.2.4 */
@@ -4841,6 +4861,17 @@ static void init_vmcs(struct vcpu_vmx *vmx)
}
vmx_setup_uret_msrs(vmx);
+
+ if (kvm_cpu_cap_has(X86_FEATURE_FRED)) {
+ vmcs_write64(GUEST_IA32_FRED_CONFIG, 0);
+ vmcs_write64(GUEST_IA32_FRED_RSP1, 0);
+ vmcs_write64(GUEST_IA32_FRED_RSP2, 0);
+ vmcs_write64(GUEST_IA32_FRED_RSP3, 0);
+ vmcs_write64(GUEST_IA32_FRED_STKLVLS, 0);
+ vmcs_write64(GUEST_IA32_FRED_SSP1, 0);
+ vmcs_write64(GUEST_IA32_FRED_SSP2, 0);
+ vmcs_write64(GUEST_IA32_FRED_SSP3, 0);
+ }
}
static void __vmx_vcpu_reset(struct kvm_vcpu *vcpu)
@@ -8717,6 +8748,11 @@ __init int vmx_hardware_setup(void)
kvm_caps.inapplicable_quirks &= ~KVM_X86_QUIRK_IGNORE_GUEST_PAT;
+ if (kvm_cpu_cap_has(X86_FEATURE_FRED)) {
+ rdmsrl(MSR_IA32_FRED_CONFIG, kvm_host.fred_config);
+ rdmsrl(MSR_IA32_FRED_STKLVLS, kvm_host.fred_stklvls);
+ }
+
return r;
}
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
index f3dc77f006f9..0c1fbf75442b 100644
--- a/arch/x86/kvm/x86.h
+++ b/arch/x86/kvm/x86.h
@@ -52,6 +52,9 @@ struct kvm_host_values {
u64 xss;
u64 s_cet;
u64 arch_capabilities;
+
+ u64 fred_config;
+ u64 fred_stklvls;
};
void kvm_spurious_fault(void);
--
2.51.0
On 10/27/2025 4:18 AM, Xin Li (Intel) wrote:
> From: Xin Li <xin3.li@intel.com>
>
> 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.
>
Reviewed-by: Binbin Wu <binbin.wu@linux.intel.com>
One nit below.
[...]
> diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
> index fcfa99160018..c8b5359123bf 100644
> --- a/arch/x86/kvm/vmx/vmx.c
> +++ b/arch/x86/kvm/vmx/vmx.c
> @@ -1459,6 +1459,15 @@ void vmx_vcpu_load_vmcs(struct kvm_vcpu *vcpu, int cpu)
> (unsigned long)(cpu_entry_stack(cpu) + 1));
> }
>
> + /* Per-CPU FRED MSRs */
> + if (kvm_cpu_cap_has(X86_FEATURE_FRED)) {
> +#ifdef CONFIG_X86_64
Nit:
Is this needed?
FRED is initialized by X86_64_F(), if CONFIG_X86_64 is not enabled, this
path is not reachable.
There should be no compilation issue without #ifdef CONFIG_X86_64 / #endif.
There are several similar patterns in this patch, using #ifdef CONFIG_X86_64 /
#endif or not seems not consistent. E.g. __vmx_vcpu_reset() and init_vmcs()
doesn't check the config, but here does.
> + vmcs_write64(HOST_IA32_FRED_RSP1, __this_cpu_ist_top_va(ESTACK_DB));
> + vmcs_write64(HOST_IA32_FRED_RSP2, __this_cpu_ist_top_va(ESTACK_NMI));
> + vmcs_write64(HOST_IA32_FRED_RSP3, __this_cpu_ist_top_va(ESTACK_DF));
> +#endif
> + }
> +
> vmx->loaded_vmcs->cpu = cpu;
> }
> }
> @@ -4330,6 +4339,17 @@ void vmx_set_constant_host_state(struct vcpu_vmx *vmx)
> */
> vmcs_write16(HOST_DS_SELECTOR, 0);
> vmcs_write16(HOST_ES_SELECTOR, 0);
> +
> + if (kvm_cpu_cap_has(X86_FEATURE_FRED)) {
> + /* FRED CONFIG and STKLVLS are the same on all CPUs */
> + vmcs_write64(HOST_IA32_FRED_CONFIG, kvm_host.fred_config);
> + vmcs_write64(HOST_IA32_FRED_STKLVLS, kvm_host.fred_stklvls);
> +
> + /* Linux doesn't support kernel shadow stacks, thus SSPs are 0s */
> + vmcs_write64(HOST_IA32_FRED_SSP1, 0);
> + vmcs_write64(HOST_IA32_FRED_SSP2, 0);
> + vmcs_write64(HOST_IA32_FRED_SSP3, 0);
> + }
> #else
> vmcs_write16(HOST_DS_SELECTOR, __KERNEL_DS); /* 22.2.4 */
> vmcs_write16(HOST_ES_SELECTOR, __KERNEL_DS); /* 22.2.4 */
> @@ -4841,6 +4861,17 @@ static void init_vmcs(struct vcpu_vmx *vmx)
> }
>
> vmx_setup_uret_msrs(vmx);
> +
> + if (kvm_cpu_cap_has(X86_FEATURE_FRED)) {
> + vmcs_write64(GUEST_IA32_FRED_CONFIG, 0);
> + vmcs_write64(GUEST_IA32_FRED_RSP1, 0);
> + vmcs_write64(GUEST_IA32_FRED_RSP2, 0);
> + vmcs_write64(GUEST_IA32_FRED_RSP3, 0);
> + vmcs_write64(GUEST_IA32_FRED_STKLVLS, 0);
> + vmcs_write64(GUEST_IA32_FRED_SSP1, 0);
> + vmcs_write64(GUEST_IA32_FRED_SSP2, 0);
> + vmcs_write64(GUEST_IA32_FRED_SSP3, 0);
> + }
> }
>
> static void __vmx_vcpu_reset(struct kvm_vcpu *vcpu)
> @@ -8717,6 +8748,11 @@ __init int vmx_hardware_setup(void)
>
> kvm_caps.inapplicable_quirks &= ~KVM_X86_QUIRK_IGNORE_GUEST_PAT;
>
> + if (kvm_cpu_cap_has(X86_FEATURE_FRED)) {
> + rdmsrl(MSR_IA32_FRED_CONFIG, kvm_host.fred_config);
> + rdmsrl(MSR_IA32_FRED_STKLVLS, kvm_host.fred_stklvls);
> + }
> +
> return r;
> }
>
> diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
> index f3dc77f006f9..0c1fbf75442b 100644
> --- a/arch/x86/kvm/x86.h
> +++ b/arch/x86/kvm/x86.h
> @@ -52,6 +52,9 @@ struct kvm_host_values {
> u64 xss;
> u64 s_cet;
> u64 arch_capabilities;
> +
> + u64 fred_config;
> + u64 fred_stklvls;
> };
>
> void kvm_spurious_fault(void);
> On Jan 20, 2026, at 10:44 PM, Binbin Wu <binbin.wu@linux.intel.com> wrote: > >> +#ifdef CONFIG_X86_64 > > Nit: > > Is this needed? > > FRED is initialized by X86_64_F(), if CONFIG_X86_64 is not enabled, this > path is not reachable. > There should be no compilation issue without #ifdef CONFIG_X86_64 / #endif. > > There are several similar patterns in this patch, using #ifdef CONFIG_X86_64 / > #endif or not seems not consistent. E.g. __vmx_vcpu_reset() and init_vmcs() > doesn't check the config, but here does. I tried removing all such #ifdef, and it turned out that I had to keep this per the last round of build checks. Anyway, I will do another build check on x86_32.
> On Jan 21, 2026, at 10:14 AM, Xin Li <xin@zytor.com> wrote:
>
>
>
>> On Jan 20, 2026, at 10:44 PM, Binbin Wu <binbin.wu@linux.intel.com> wrote:
>>
>>> +#ifdef CONFIG_X86_64
>>
>> Nit:
>>
>> Is this needed?
>>
>> FRED is initialized by X86_64_F(), if CONFIG_X86_64 is not enabled, this
>> path is not reachable.
>> There should be no compilation issue without #ifdef CONFIG_X86_64 / #endif.
>>
>> There are several similar patterns in this patch, using #ifdef CONFIG_X86_64 /
>> #endif or not seems not consistent. E.g. __vmx_vcpu_reset() and init_vmcs()
>> doesn't check the config, but here does.
>
>
> I tried removing all such #ifdef, and it turned out that I had to keep this
> per the last round of build checks.
>
> Anyway, I will do another build check on x86_32.
>
The trouble comes from __this_cpu_ist_top_va():
arch/x86/kvm/vmx/vmx.c: In function ‘vmx_vcpu_load_vmcs’:
arch/x86/kvm/vmx/vmx.c:1608:59: error: implicit declaration of function ‘__this_cpu_ist_top_va’ [-Werror=implicit-function-declaration]
1608 | vmcs_write64(HOST_IA32_FRED_RSP1, __this_cpu_ist_top_va(ESTACK_DB));
| ^~~~~~~~~~~~~~~~~~~~~
arch/x86/kvm/vmx/vmx.c:1608:81: error: ‘ESTACK_DB’ undeclared (first use in this function)
1608 | vmcs_write64(HOST_IA32_FRED_RSP1, __this_cpu_ist_top_va(ESTACK_DB));
| ^~~~~~~~~
arch/x86/kvm/vmx/vmx.c:1608:81: note: each undeclared identifier is reported only once for each function it appears in
CC [M] crypto/md4.o
CC lib/crypto/sha512.o
arch/x86/kvm/vmx/vmx.c:1609:81: error: ‘ESTACK_NMI’ undeclared (first use in this function)
1609 | vmcs_write64(HOST_IA32_FRED_RSP2, __this_cpu_ist_top_va(ESTACK_NMI));
| ^~~~~~~~~~
arch/x86/kvm/vmx/vmx.c:1610:81: error: ‘ESTACK_DF’ undeclared (first use in this function)
1610 | vmcs_write64(HOST_IA32_FRED_RSP3, __this_cpu_ist_top_va(ESTACK_DF));
| ^~~~~~~~~
On 1/22/2026 8:45 AM, Xin Li wrote: > > >> On Jan 21, 2026, at 10:14 AM, Xin Li <xin@zytor.com> wrote: >> >> >> >>> On Jan 20, 2026, at 10:44 PM, Binbin Wu <binbin.wu@linux.intel.com> wrote: >>> >>>> +#ifdef CONFIG_X86_64 >>> >>> Nit: >>> >>> Is this needed? >>> >>> FRED is initialized by X86_64_F(), if CONFIG_X86_64 is not enabled, this >>> path is not reachable. >>> There should be no compilation issue without #ifdef CONFIG_X86_64 / #endif. >>> >>> There are several similar patterns in this patch, using #ifdef CONFIG_X86_64 / >>> #endif or not seems not consistent. E.g. __vmx_vcpu_reset() and init_vmcs() >>> doesn't check the config, but here does. >> >> >> I tried removing all such #ifdef, and it turned out that I had to keep this >> per the last round of build checks. >> >> Anyway, I will do another build check on x86_32. >> > > > The trouble comes from __this_cpu_ist_top_va(): Oh, right! Sorry for the noise. > > arch/x86/kvm/vmx/vmx.c: In function ‘vmx_vcpu_load_vmcs’: > arch/x86/kvm/vmx/vmx.c:1608:59: error: implicit declaration of function ‘__this_cpu_ist_top_va’ [-Werror=implicit-function-declaration] > 1608 | vmcs_write64(HOST_IA32_FRED_RSP1, __this_cpu_ist_top_va(ESTACK_DB)); > | ^~~~~~~~~~~~~~~~~~~~~ > arch/x86/kvm/vmx/vmx.c:1608:81: error: ‘ESTACK_DB’ undeclared (first use in this function) > 1608 | vmcs_write64(HOST_IA32_FRED_RSP1, __this_cpu_ist_top_va(ESTACK_DB)); > | ^~~~~~~~~ > arch/x86/kvm/vmx/vmx.c:1608:81: note: each undeclared identifier is reported only once for each function it appears in > CC [M] crypto/md4.o > CC lib/crypto/sha512.o > arch/x86/kvm/vmx/vmx.c:1609:81: error: ‘ESTACK_NMI’ undeclared (first use in this function) > 1609 | vmcs_write64(HOST_IA32_FRED_RSP2, __this_cpu_ist_top_va(ESTACK_NMI)); > | ^~~~~~~~~~ > arch/x86/kvm/vmx/vmx.c:1610:81: error: ‘ESTACK_DF’ undeclared (first use in this function) > 1610 | vmcs_write64(HOST_IA32_FRED_RSP3, __this_cpu_ist_top_va(ESTACK_DF)); > | ^~~~~~~~~ >
>> The trouble comes from __this_cpu_ist_top_va():
>
> Oh, right!
> Sorry for the noise.
It’s absolutely NOT noise, because we don’t like #ifdef in C file.
With the following additional patch, we can remove this #ifdef CONFIG_X86_64:
diff --git a/arch/x86/include/asm/cpu_entry_area.h b/arch/x86/include/asm/cpu_entry_area.h
index 509e52fc3a0f..c35ef2cb9b8a 100644
--- a/arch/x86/include/asm/cpu_entry_area.h
+++ b/arch/x86/include/asm/cpu_entry_area.h
@@ -8,14 +8,6 @@
#include <asm/intel_ds.h>
#include <asm/pgtable_areas.h>
-#ifdef CONFIG_X86_64
-
-#ifdef CONFIG_AMD_MEM_ENCRYPT
-#define VC_EXCEPTION_STKSZ EXCEPTION_STKSZ
-#else
-#define VC_EXCEPTION_STKSZ 0
-#endif
-
/*
* The exception stack ordering in [cea_]exception_stacks
*/
@@ -26,9 +18,19 @@ enum exception_stack_ordering {
ESTACK_MCE,
ESTACK_VC,
ESTACK_VC2,
+#ifdef CONFIG_X86_64
N_EXCEPTION_STACKS
+#endif
};
+#ifdef CONFIG_X86_64
+
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+#define VC_EXCEPTION_STKSZ EXCEPTION_STKSZ
+#else
+#define VC_EXCEPTION_STKSZ 0
+#endif
+
/* Macro to enforce the same ordering and stack sizes */
#define ESTACKS_MEMBERS(guardsize, optional_stack_size) \
char ESTACK_DF_stack_guard[guardsize]; \
@@ -75,6 +77,11 @@ struct doublefault_stack {
unsigned long stack[(PAGE_SIZE - sizeof(struct x86_hw_tss)) / sizeof(unsigned long)];
struct x86_hw_tss tss;
} __aligned(PAGE_SIZE);
+
+static inline unsigned long __this_cpu_ist_top_va(enum exception_stack_ordering stack)
+{
+ return 0;
+}
#endif
/*
Another simpler way to define __this_cpu_ist_top_va() in a VMX header, but
I don’t think it’s the right way.
On Sun, Oct 26, 2025 at 01:18:55PM -0700, Xin Li (Intel) wrote:
>From: Xin Li <xin3.li@intel.com>
>
>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 <xin3.li@intel.com>
>Signed-off-by: Xin Li (Intel) <xin@zytor.com>
>Tested-by: Shan Kang <shan.kang@intel.com>
>Tested-by: Xuelian Guo <xuelian.guo@intel.com>
Reviewed-by: Chao Gao <chao.gao@intel.com>
one nit below,
>@@ -8717,6 +8748,11 @@ __init int vmx_hardware_setup(void)
>
> kvm_caps.inapplicable_quirks &= ~KVM_X86_QUIRK_IGNORE_GUEST_PAT;
>
>+ if (kvm_cpu_cap_has(X86_FEATURE_FRED)) {
>+ rdmsrl(MSR_IA32_FRED_CONFIG, kvm_host.fred_config);
>+ rdmsrl(MSR_IA32_FRED_STKLVLS, kvm_host.fred_stklvls);
s/rdmsrl/rdmsrq
>+ }
>+
> return r;
> }
>
>diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
>index f3dc77f006f9..0c1fbf75442b 100644
>--- a/arch/x86/kvm/x86.h
>+++ b/arch/x86/kvm/x86.h
>@@ -52,6 +52,9 @@ struct kvm_host_values {
> u64 xss;
> u64 s_cet;
> u64 arch_capabilities;
>+
>+ u64 fred_config;
>+ u64 fred_stklvls;
> };
>
> void kvm_spurious_fault(void);
>--
>2.51.0
>
© 2016 - 2026 Red Hat, Inc.