[PATCH v9 07/22] KVM: VMX: Initialize VMCS FRED fields

Xin Li (Intel) posted 22 patches 3 months, 2 weeks ago
[PATCH v9 07/22] KVM: VMX: Initialize VMCS FRED fields
Posted by Xin Li (Intel) 3 months, 2 weeks ago
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
Re: [PATCH v9 07/22] KVM: VMX: Initialize VMCS FRED fields
Posted by Binbin Wu 2 weeks, 5 days ago

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);
Re: [PATCH v9 07/22] KVM: VMX: Initialize VMCS FRED fields
Posted by Xin Li 2 weeks, 4 days ago

> 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.
Re: [PATCH v9 07/22] KVM: VMX: Initialize VMCS FRED fields
Posted by Xin Li 2 weeks, 4 days ago

> 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));
      |                                                                                 ^~~~~~~~~
Re: [PATCH v9 07/22] KVM: VMX: Initialize VMCS FRED fields
Posted by Binbin Wu 2 weeks, 4 days ago

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));
>       |                                                                                 ^~~~~~~~~
> 

Re: [PATCH v9 07/22] KVM: VMX: Initialize VMCS FRED fields
Posted by Xin Li 2 weeks, 3 days ago
>> 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.
Re: [PATCH v9 07/22] KVM: VMX: Initialize VMCS FRED fields
Posted by Chao Gao 2 months, 3 weeks ago
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
>