[PATCH v2 1/3] KVM: x86: Explicitly configure supported XSS from {svm,vmx}_set_cpu_caps()

Sean Christopherson posted 3 patches 1 week, 4 days ago
[PATCH v2 1/3] KVM: x86: Explicitly configure supported XSS from {svm,vmx}_set_cpu_caps()
Posted by Sean Christopherson 1 week, 4 days ago
Explicitly configure KVM's supported XSS as part of each vendor's setup
flow to fix a bug where clearing SHSTK and IBT in kvm_cpu_caps, e.g. due
to lack of CET XFEATURE support, makes kvm-intel.ko unloadable when nested
VMX is enabled, i.e. when nested=1.  The late clearing results in
nested_vmx_setup_{entry,exit}_ctls() clearing VM_{ENTRY,EXIT}_LOAD_CET_STATE
when nested_vmx_setup_ctls_msrs() runs during the CPU compatibility checks,
ultimately leading to a mismatched VMCS config due to the reference config
having the CET bits set, but every CPU's "local" config having the bits
cleared.

Note, kvm_caps.supported_{xcr0,xss} are unconditionally initialized by
kvm_x86_vendor_init(), before calling into vendor code, and not referenced
between ops->hardware_setup() and their current/old location.

Fixes: 69cc3e886582 ("KVM: x86: Add XSS support for CET_KERNEL and CET_USER")
Cc: stable@vger.kernel.org
Cc: Mathias Krause <minipli@grsecurity.net>
Cc: John Allen <john.allen@amd.com>
Cc: Rick Edgecombe <rick.p.edgecombe@intel.com>
Cc: Chao Gao <chao.gao@intel.com>
Cc: Binbin Wu <binbin.wu@linux.intel.com>
Cc: Xiaoyao Li <xiaoyao.li@intel.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 arch/x86/kvm/svm/svm.c |  2 ++
 arch/x86/kvm/vmx/vmx.c |  2 ++
 arch/x86/kvm/x86.c     | 30 +++++++++++++++++-------------
 arch/x86/kvm/x86.h     |  2 ++
 4 files changed, 23 insertions(+), 13 deletions(-)

diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 7803d2781144..c00a696dacfc 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -5387,6 +5387,8 @@ static __init void svm_set_cpu_caps(void)
 	 */
 	kvm_cpu_cap_clear(X86_FEATURE_BUS_LOCK_DETECT);
 	kvm_cpu_cap_clear(X86_FEATURE_MSR_IMM);
+
+	kvm_setup_xss_caps();
 }
 
 static __init int svm_hardware_setup(void)
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 27acafd03381..9f85c3829890 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -8230,6 +8230,8 @@ static __init void vmx_set_cpu_caps(void)
 		kvm_cpu_cap_clear(X86_FEATURE_SHSTK);
 		kvm_cpu_cap_clear(X86_FEATURE_IBT);
 	}
+
+	kvm_setup_xss_caps();
 }
 
 static bool vmx_is_io_intercepted(struct kvm_vcpu *vcpu,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 8acfdfc583a1..cac1d6a67b49 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -9965,6 +9965,23 @@ static struct notifier_block pvclock_gtod_notifier = {
 };
 #endif
 
+void kvm_setup_xss_caps(void)
+{
+	if (!kvm_cpu_cap_has(X86_FEATURE_XSAVES))
+		kvm_caps.supported_xss = 0;
+
+	if (!kvm_cpu_cap_has(X86_FEATURE_SHSTK) &&
+	    !kvm_cpu_cap_has(X86_FEATURE_IBT))
+		kvm_caps.supported_xss &= ~XFEATURE_MASK_CET_ALL;
+
+	if ((kvm_caps.supported_xss & XFEATURE_MASK_CET_ALL) != XFEATURE_MASK_CET_ALL) {
+		kvm_cpu_cap_clear(X86_FEATURE_SHSTK);
+		kvm_cpu_cap_clear(X86_FEATURE_IBT);
+		kvm_caps.supported_xss &= ~XFEATURE_MASK_CET_ALL;
+	}
+}
+EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_setup_xss_caps);
+
 static inline void kvm_ops_update(struct kvm_x86_init_ops *ops)
 {
 	memcpy(&kvm_x86_ops, ops->runtime_ops, sizeof(kvm_x86_ops));
@@ -10138,19 +10155,6 @@ int kvm_x86_vendor_init(struct kvm_x86_init_ops *ops)
 	if (!tdp_enabled)
 		kvm_caps.supported_quirks &= ~KVM_X86_QUIRK_IGNORE_GUEST_PAT;
 
-	if (!kvm_cpu_cap_has(X86_FEATURE_XSAVES))
-		kvm_caps.supported_xss = 0;
-
-	if (!kvm_cpu_cap_has(X86_FEATURE_SHSTK) &&
-	    !kvm_cpu_cap_has(X86_FEATURE_IBT))
-		kvm_caps.supported_xss &= ~XFEATURE_MASK_CET_ALL;
-
-	if ((kvm_caps.supported_xss & XFEATURE_MASK_CET_ALL) != XFEATURE_MASK_CET_ALL) {
-		kvm_cpu_cap_clear(X86_FEATURE_SHSTK);
-		kvm_cpu_cap_clear(X86_FEATURE_IBT);
-		kvm_caps.supported_xss &= ~XFEATURE_MASK_CET_ALL;
-	}
-
 	if (kvm_caps.has_tsc_control) {
 		/*
 		 * Make sure the user can only configure tsc_khz values that
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
index 70e81f008030..94d4f07aaaa0 100644
--- a/arch/x86/kvm/x86.h
+++ b/arch/x86/kvm/x86.h
@@ -483,6 +483,8 @@ extern struct kvm_host_values kvm_host;
 extern bool enable_pmu;
 extern bool enable_mediated_pmu;
 
+void kvm_setup_xss_caps(void);
+
 /*
  * Get a filtered version of KVM's supported XCR0 that strips out dynamic
  * features for which the current process doesn't (yet) have permission to use.
-- 
2.52.0.457.g6b5491de43-goog
Re: [PATCH v2 1/3] KVM: x86: Explicitly configure supported XSS from {svm,vmx}_set_cpu_caps()
Posted by Binbin Wu 1 week, 2 days ago

On 1/28/2026 9:43 AM, Sean Christopherson wrote:
> Explicitly configure KVM's supported XSS as part of each vendor's setup
> flow to fix a bug where clearing SHSTK and IBT in kvm_cpu_caps, e.g. due
> to lack of CET XFEATURE support, makes kvm-intel.ko unloadable when nested
> VMX is enabled, i.e. when nested=1.  The late clearing results in
> nested_vmx_setup_{entry,exit}_ctls() clearing VM_{ENTRY,EXIT}_LOAD_CET_STATE
> when nested_vmx_setup_ctls_msrs() runs during the CPU compatibility checks,
> ultimately leading to a mismatched VMCS config due to the reference config
> having the CET bits set, but every CPU's "local" config having the bits
> cleared.
> 
> Note, kvm_caps.supported_{xcr0,xss} are unconditionally initialized by
> kvm_x86_vendor_init(), before calling into vendor code, and not referenced
> between ops->hardware_setup() and their current/old location.
> 

Reviewed-by: Binbin Wu <binbin.wu@linux.intel.com>

> Fixes: 69cc3e886582 ("KVM: x86: Add XSS support for CET_KERNEL and CET_USER")
> Cc: stable@vger.kernel.org
> Cc: Mathias Krause <minipli@grsecurity.net>
> Cc: John Allen <john.allen@amd.com>
> Cc: Rick Edgecombe <rick.p.edgecombe@intel.com>
> Cc: Chao Gao <chao.gao@intel.com>
> Cc: Binbin Wu <binbin.wu@linux.intel.com>
> Cc: Xiaoyao Li <xiaoyao.li@intel.com>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
>  arch/x86/kvm/svm/svm.c |  2 ++
>  arch/x86/kvm/vmx/vmx.c |  2 ++
>  arch/x86/kvm/x86.c     | 30 +++++++++++++++++-------------
>  arch/x86/kvm/x86.h     |  2 ++
>  4 files changed, 23 insertions(+), 13 deletions(-)
> 
> diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
> index 7803d2781144..c00a696dacfc 100644
> --- a/arch/x86/kvm/svm/svm.c
> +++ b/arch/x86/kvm/svm/svm.c
> @@ -5387,6 +5387,8 @@ static __init void svm_set_cpu_caps(void)
>  	 */
>  	kvm_cpu_cap_clear(X86_FEATURE_BUS_LOCK_DETECT);
>  	kvm_cpu_cap_clear(X86_FEATURE_MSR_IMM);
> +
> +	kvm_setup_xss_caps();
>  }
>  
>  static __init int svm_hardware_setup(void)
> diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
> index 27acafd03381..9f85c3829890 100644
> --- a/arch/x86/kvm/vmx/vmx.c
> +++ b/arch/x86/kvm/vmx/vmx.c
> @@ -8230,6 +8230,8 @@ static __init void vmx_set_cpu_caps(void)
>  		kvm_cpu_cap_clear(X86_FEATURE_SHSTK);
>  		kvm_cpu_cap_clear(X86_FEATURE_IBT);
>  	}
> +
> +	kvm_setup_xss_caps();
>  }
>  
>  static bool vmx_is_io_intercepted(struct kvm_vcpu *vcpu,
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 8acfdfc583a1..cac1d6a67b49 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -9965,6 +9965,23 @@ static struct notifier_block pvclock_gtod_notifier = {
>  };
>  #endif
>  
> +void kvm_setup_xss_caps(void)
> +{
> +	if (!kvm_cpu_cap_has(X86_FEATURE_XSAVES))
> +		kvm_caps.supported_xss = 0;
> +
> +	if (!kvm_cpu_cap_has(X86_FEATURE_SHSTK) &&
> +	    !kvm_cpu_cap_has(X86_FEATURE_IBT))
> +		kvm_caps.supported_xss &= ~XFEATURE_MASK_CET_ALL;
> +
> +	if ((kvm_caps.supported_xss & XFEATURE_MASK_CET_ALL) != XFEATURE_MASK_CET_ALL) {
> +		kvm_cpu_cap_clear(X86_FEATURE_SHSTK);
> +		kvm_cpu_cap_clear(X86_FEATURE_IBT);
> +		kvm_caps.supported_xss &= ~XFEATURE_MASK_CET_ALL;
> +	}
> +}
> +EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_setup_xss_caps);
> +
>  static inline void kvm_ops_update(struct kvm_x86_init_ops *ops)
>  {
>  	memcpy(&kvm_x86_ops, ops->runtime_ops, sizeof(kvm_x86_ops));
> @@ -10138,19 +10155,6 @@ int kvm_x86_vendor_init(struct kvm_x86_init_ops *ops)
>  	if (!tdp_enabled)
>  		kvm_caps.supported_quirks &= ~KVM_X86_QUIRK_IGNORE_GUEST_PAT;
>  
> -	if (!kvm_cpu_cap_has(X86_FEATURE_XSAVES))
> -		kvm_caps.supported_xss = 0;
> -
> -	if (!kvm_cpu_cap_has(X86_FEATURE_SHSTK) &&
> -	    !kvm_cpu_cap_has(X86_FEATURE_IBT))
> -		kvm_caps.supported_xss &= ~XFEATURE_MASK_CET_ALL;
> -
> -	if ((kvm_caps.supported_xss & XFEATURE_MASK_CET_ALL) != XFEATURE_MASK_CET_ALL) {
> -		kvm_cpu_cap_clear(X86_FEATURE_SHSTK);
> -		kvm_cpu_cap_clear(X86_FEATURE_IBT);
> -		kvm_caps.supported_xss &= ~XFEATURE_MASK_CET_ALL;
> -	}
> -
>  	if (kvm_caps.has_tsc_control) {
>  		/*
>  		 * Make sure the user can only configure tsc_khz values that
> diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
> index 70e81f008030..94d4f07aaaa0 100644
> --- a/arch/x86/kvm/x86.h
> +++ b/arch/x86/kvm/x86.h
> @@ -483,6 +483,8 @@ extern struct kvm_host_values kvm_host;
>  extern bool enable_pmu;
>  extern bool enable_mediated_pmu;
>  
> +void kvm_setup_xss_caps(void);
> +
>  /*
>   * Get a filtered version of KVM's supported XCR0 that strips out dynamic
>   * features for which the current process doesn't (yet) have permission to use.
Re: [PATCH v2 1/3] KVM: x86: Explicitly configure supported XSS from {svm,vmx}_set_cpu_caps()
Posted by Binbin Wu 1 week, 3 days ago

On 1/28/2026 9:43 AM, Sean Christopherson wrote:
> Explicitly configure KVM's supported XSS as part of each vendor's setup
> flow to fix a bug where clearing SHSTK and IBT in kvm_cpu_caps, e.g. due
> to lack of CET XFEATURE support, makes kvm-intel.ko unloadable when nested
> VMX is enabled, i.e. when nested=1.  The late clearing results in
> nested_vmx_setup_{entry,exit}_ctls() clearing VM_{ENTRY,EXIT}_LOAD_CET_STATE
> when nested_vmx_setup_ctls_msrs() runs during the CPU compatibility checks,
> ultimately leading to a mismatched VMCS config due to the reference config
> having the CET bits set, but every CPU's "local" config having the bits
> cleared.

A bit confuse about the description.

Before this patch:

kvm_x86_vendor_init
| vmx_hardware_setup
|   nested_vmx_hardware_setup
|     nested_vmx_setup_ctls_msrs
| ...
| for_each_online_cpu(cpu)
|   smp_call_function_single(cpu, kvm_x86_check_cpu_compat, &r, 1)
|                                 | kvm_x86_check_processor_compatibility
|                                 |   kvm_x86_call(check_processor_compatibility)()
|                                 |     vmx_check_processor_compatibility
|                                 |       setup_vmcs_config
|                                 |         nested_vmx_setup_ctls_msrs
| ...
| //late clearing of SHSTK and IBT

If we don't consider CPU hotplug case, both the setup of reference VMCS and the
local config are before the late clearing of SHSTK and IBT. They should be
consistent.

So you are referring the mismatch situation during CPU hotplug?

But if it's hotplug case, it shouldn't make kvm-intel.ko unloadable?


> 
> Note, kvm_caps.supported_{xcr0,xss} are unconditionally initialized by
> kvm_x86_vendor_init(), before calling into vendor code, and not referenced
> between ops->hardware_setup() and their current/old location.
> 
> Fixes: 69cc3e886582 ("KVM: x86: Add XSS support for CET_KERNEL and CET_USER")
> Cc: stable@vger.kernel.org
> Cc: Mathias Krause <minipli@grsecurity.net>
> Cc: John Allen <john.allen@amd.com>
> Cc: Rick Edgecombe <rick.p.edgecombe@intel.com>
> Cc: Chao Gao <chao.gao@intel.com>
> Cc: Binbin Wu <binbin.wu@linux.intel.com>
> Cc: Xiaoyao Li <xiaoyao.li@intel.com>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
>  arch/x86/kvm/svm/svm.c |  2 ++
>  arch/x86/kvm/vmx/vmx.c |  2 ++
>  arch/x86/kvm/x86.c     | 30 +++++++++++++++++-------------
>  arch/x86/kvm/x86.h     |  2 ++
>  4 files changed, 23 insertions(+), 13 deletions(-)
> 
> diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
> index 7803d2781144..c00a696dacfc 100644
> --- a/arch/x86/kvm/svm/svm.c
> +++ b/arch/x86/kvm/svm/svm.c
> @@ -5387,6 +5387,8 @@ static __init void svm_set_cpu_caps(void)
>  	 */
>  	kvm_cpu_cap_clear(X86_FEATURE_BUS_LOCK_DETECT);
>  	kvm_cpu_cap_clear(X86_FEATURE_MSR_IMM);
> +
> +	kvm_setup_xss_caps();
>  }
>  
>  static __init int svm_hardware_setup(void)
> diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
> index 27acafd03381..9f85c3829890 100644
> --- a/arch/x86/kvm/vmx/vmx.c
> +++ b/arch/x86/kvm/vmx/vmx.c
> @@ -8230,6 +8230,8 @@ static __init void vmx_set_cpu_caps(void)
>  		kvm_cpu_cap_clear(X86_FEATURE_SHSTK);
>  		kvm_cpu_cap_clear(X86_FEATURE_IBT);
>  	}
> +
> +	kvm_setup_xss_caps();
>  }
>  
>  static bool vmx_is_io_intercepted(struct kvm_vcpu *vcpu,
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 8acfdfc583a1..cac1d6a67b49 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -9965,6 +9965,23 @@ static struct notifier_block pvclock_gtod_notifier = {
>  };
>  #endif
>  
> +void kvm_setup_xss_caps(void)
> +{
> +	if (!kvm_cpu_cap_has(X86_FEATURE_XSAVES))
> +		kvm_caps.supported_xss = 0;
> +
> +	if (!kvm_cpu_cap_has(X86_FEATURE_SHSTK) &&
> +	    !kvm_cpu_cap_has(X86_FEATURE_IBT))
> +		kvm_caps.supported_xss &= ~XFEATURE_MASK_CET_ALL;
> +
> +	if ((kvm_caps.supported_xss & XFEATURE_MASK_CET_ALL) != XFEATURE_MASK_CET_ALL) {
> +		kvm_cpu_cap_clear(X86_FEATURE_SHSTK);
> +		kvm_cpu_cap_clear(X86_FEATURE_IBT);
> +		kvm_caps.supported_xss &= ~XFEATURE_MASK_CET_ALL;
> +	}
> +}
> +EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_setup_xss_caps);
> +
>  static inline void kvm_ops_update(struct kvm_x86_init_ops *ops)
>  {
>  	memcpy(&kvm_x86_ops, ops->runtime_ops, sizeof(kvm_x86_ops));
> @@ -10138,19 +10155,6 @@ int kvm_x86_vendor_init(struct kvm_x86_init_ops *ops)
>  	if (!tdp_enabled)
>  		kvm_caps.supported_quirks &= ~KVM_X86_QUIRK_IGNORE_GUEST_PAT;
>  
> -	if (!kvm_cpu_cap_has(X86_FEATURE_XSAVES))
> -		kvm_caps.supported_xss = 0;
> -
> -	if (!kvm_cpu_cap_has(X86_FEATURE_SHSTK) &&
> -	    !kvm_cpu_cap_has(X86_FEATURE_IBT))
> -		kvm_caps.supported_xss &= ~XFEATURE_MASK_CET_ALL;
> -
> -	if ((kvm_caps.supported_xss & XFEATURE_MASK_CET_ALL) != XFEATURE_MASK_CET_ALL) {
> -		kvm_cpu_cap_clear(X86_FEATURE_SHSTK);
> -		kvm_cpu_cap_clear(X86_FEATURE_IBT);
> -		kvm_caps.supported_xss &= ~XFEATURE_MASK_CET_ALL;
> -	}
> -
>  	if (kvm_caps.has_tsc_control) {
>  		/*
>  		 * Make sure the user can only configure tsc_khz values that
> diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
> index 70e81f008030..94d4f07aaaa0 100644
> --- a/arch/x86/kvm/x86.h
> +++ b/arch/x86/kvm/x86.h
> @@ -483,6 +483,8 @@ extern struct kvm_host_values kvm_host;
>  extern bool enable_pmu;
>  extern bool enable_mediated_pmu;
>  
> +void kvm_setup_xss_caps(void);
> +
>  /*
>   * Get a filtered version of KVM's supported XCR0 that strips out dynamic
>   * features for which the current process doesn't (yet) have permission to use.
Re: [PATCH v2 1/3] KVM: x86: Explicitly configure supported XSS from {svm,vmx}_set_cpu_caps()
Posted by Xiaoyao Li 1 week, 2 days ago
On 1/29/2026 3:34 PM, Binbin Wu wrote:
> 
> 
> On 1/28/2026 9:43 AM, Sean Christopherson wrote:
>> Explicitly configure KVM's supported XSS as part of each vendor's setup
>> flow to fix a bug where clearing SHSTK and IBT in kvm_cpu_caps, e.g. due
>> to lack of CET XFEATURE support, makes kvm-intel.ko unloadable when nested
>> VMX is enabled, i.e. when nested=1.  The late clearing results in
>> nested_vmx_setup_{entry,exit}_ctls() clearing VM_{ENTRY,EXIT}_LOAD_CET_STATE
>> when nested_vmx_setup_ctls_msrs() runs during the CPU compatibility checks,
>> ultimately leading to a mismatched VMCS config due to the reference config
>> having the CET bits set, but every CPU's "local" config having the bits
>> cleared.
> 
> A bit confuse about the description.
> 
> Before this patch:
> 
> kvm_x86_vendor_init
> | vmx_hardware_setup
> |   nested_vmx_hardware_setup
> |     nested_vmx_setup_ctls_msrs
> | ...
> | for_each_online_cpu(cpu)
> |   smp_call_function_single(cpu, kvm_x86_check_cpu_compat, &r, 1)
> |                                 | kvm_x86_check_processor_compatibility
> |                                 |   kvm_x86_call(check_processor_compatibility)()
> |                                 |     vmx_check_processor_compatibility
> |                                 |       setup_vmcs_config
> |                                 |         nested_vmx_setup_ctls_msrs
> | ...
> | //late clearing of SHSTK and IBT
> 
> If we don't consider CPU hotplug case, both the setup of reference VMCS and the
> local config are before the late clearing of SHSTK and IBT. They should be
> consistent.
> 
> So you are referring the mismatch situation during CPU hotplug?

I guess it's triggered the path

   kvm_init()
     kvm_init_virtualization()
       kvm_enable_virtualization()
         cpuhp_setup_state()
           kvm_online_cpu()
             ...

   (note, it requires enable_virt_at_load to be true)

which is after
   vmx_init()
     kvm_x86_vendor_init()
Re: [PATCH v2 1/3] KVM: x86: Explicitly configure supported XSS from {svm,vmx}_set_cpu_caps()
Posted by Binbin Wu 1 week, 2 days ago

On 1/30/2026 11:23 AM, Xiaoyao Li wrote:
> On 1/29/2026 3:34 PM, Binbin Wu wrote:
>>
>>
>> On 1/28/2026 9:43 AM, Sean Christopherson wrote:
>>> Explicitly configure KVM's supported XSS as part of each vendor's setup
>>> flow to fix a bug where clearing SHSTK and IBT in kvm_cpu_caps, e.g. due
>>> to lack of CET XFEATURE support, makes kvm-intel.ko unloadable when nested
>>> VMX is enabled, i.e. when nested=1.  The late clearing results in
>>> nested_vmx_setup_{entry,exit}_ctls() clearing VM_{ENTRY,EXIT}_LOAD_CET_STATE
>>> when nested_vmx_setup_ctls_msrs() runs during the CPU compatibility checks,
>>> ultimately leading to a mismatched VMCS config due to the reference config
>>> having the CET bits set, but every CPU's "local" config having the bits
>>> cleared.
>>
>> A bit confuse about the description.
>>
>> Before this patch:
>>
>> kvm_x86_vendor_init
>> | vmx_hardware_setup
>> |   nested_vmx_hardware_setup
>> |     nested_vmx_setup_ctls_msrs
>> | ...
>> | for_each_online_cpu(cpu)
>> |   smp_call_function_single(cpu, kvm_x86_check_cpu_compat, &r, 1)
>> |                                 | kvm_x86_check_processor_compatibility
>> |                                 |   kvm_x86_call(check_processor_compatibility)()
>> |                                 |     vmx_check_processor_compatibility
>> |                                 |       setup_vmcs_config
>> |                                 |         nested_vmx_setup_ctls_msrs
>> | ...
>> | //late clearing of SHSTK and IBT
>>
>> If we don't consider CPU hotplug case, both the setup of reference VMCS and the
>> local config are before the late clearing of SHSTK and IBT. They should be
>> consistent.
>>
>> So you are referring the mismatch situation during CPU hotplug?
> 
> I guess it's triggered the path
> 
>   kvm_init()
>     kvm_init_virtualization()
>       kvm_enable_virtualization()
>         cpuhp_setup_state()
>           kvm_online_cpu()
>             ...
> 
>   (note, it requires enable_virt_at_load to be true)
> 
> which is after
>   vmx_init()
>     kvm_x86_vendor_init()
> 

Oh, right.
Forgot about that by default KVM enables virtualization when KVM is loaded,
which trigger the cpuhp framework to do per-CPU enabling.

Thanks!

Re: [PATCH v2 1/3] KVM: x86: Explicitly configure supported XSS from {svm,vmx}_set_cpu_caps()
Posted by Xiaoyao Li 1 week, 3 days ago
On 1/28/2026 9:43 AM, Sean Christopherson wrote:
> Explicitly configure KVM's supported XSS as part of each vendor's setup
> flow to fix a bug where clearing SHSTK and IBT in kvm_cpu_caps, e.g. due
> to lack of CET XFEATURE support, makes kvm-intel.ko unloadable when nested
> VMX is enabled, i.e. when nested=1.  The late clearing results in
> nested_vmx_setup_{entry,exit}_ctls() clearing VM_{ENTRY,EXIT}_LOAD_CET_STATE
> when nested_vmx_setup_ctls_msrs() runs during the CPU compatibility checks,
> ultimately leading to a mismatched VMCS config due to the reference config
> having the CET bits set, but every CPU's "local" config having the bits
> cleared.
> 
> Note, kvm_caps.supported_{xcr0,xss} are unconditionally initialized by
> kvm_x86_vendor_init(), before calling into vendor code, and not referenced
> between ops->hardware_setup() and their current/old location.

I'm thinking whether to move the initialization of supported_xss from 
kvm_x86_vendor_init() to kvm_setup_xss_caps(). Anyway it can be a 
separate patch, if we agree to make the change.

For this fixing patch,

Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com>

> Fixes: 69cc3e886582 ("KVM: x86: Add XSS support for CET_KERNEL and CET_USER")
> Cc: stable@vger.kernel.org
> Cc: Mathias Krause <minipli@grsecurity.net>
> Cc: John Allen <john.allen@amd.com>
> Cc: Rick Edgecombe <rick.p.edgecombe@intel.com>
> Cc: Chao Gao <chao.gao@intel.com>
> Cc: Binbin Wu <binbin.wu@linux.intel.com>
> Cc: Xiaoyao Li <xiaoyao.li@intel.com>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
>   arch/x86/kvm/svm/svm.c |  2 ++
>   arch/x86/kvm/vmx/vmx.c |  2 ++
>   arch/x86/kvm/x86.c     | 30 +++++++++++++++++-------------
>   arch/x86/kvm/x86.h     |  2 ++
>   4 files changed, 23 insertions(+), 13 deletions(-)
> 
> diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
> index 7803d2781144..c00a696dacfc 100644
> --- a/arch/x86/kvm/svm/svm.c
> +++ b/arch/x86/kvm/svm/svm.c
> @@ -5387,6 +5387,8 @@ static __init void svm_set_cpu_caps(void)
>   	 */
>   	kvm_cpu_cap_clear(X86_FEATURE_BUS_LOCK_DETECT);
>   	kvm_cpu_cap_clear(X86_FEATURE_MSR_IMM);
> +
> +	kvm_setup_xss_caps();
>   }
>   
>   static __init int svm_hardware_setup(void)
> diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
> index 27acafd03381..9f85c3829890 100644
> --- a/arch/x86/kvm/vmx/vmx.c
> +++ b/arch/x86/kvm/vmx/vmx.c
> @@ -8230,6 +8230,8 @@ static __init void vmx_set_cpu_caps(void)
>   		kvm_cpu_cap_clear(X86_FEATURE_SHSTK);
>   		kvm_cpu_cap_clear(X86_FEATURE_IBT);
>   	}
> +
> +	kvm_setup_xss_caps();
>   }
>   
>   static bool vmx_is_io_intercepted(struct kvm_vcpu *vcpu,
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 8acfdfc583a1..cac1d6a67b49 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -9965,6 +9965,23 @@ static struct notifier_block pvclock_gtod_notifier = {
>   };
>   #endif
>   
> +void kvm_setup_xss_caps(void)
> +{
> +	if (!kvm_cpu_cap_has(X86_FEATURE_XSAVES))
> +		kvm_caps.supported_xss = 0;
> +
> +	if (!kvm_cpu_cap_has(X86_FEATURE_SHSTK) &&
> +	    !kvm_cpu_cap_has(X86_FEATURE_IBT))
> +		kvm_caps.supported_xss &= ~XFEATURE_MASK_CET_ALL;
> +
> +	if ((kvm_caps.supported_xss & XFEATURE_MASK_CET_ALL) != XFEATURE_MASK_CET_ALL) {
> +		kvm_cpu_cap_clear(X86_FEATURE_SHSTK);
> +		kvm_cpu_cap_clear(X86_FEATURE_IBT);
> +		kvm_caps.supported_xss &= ~XFEATURE_MASK_CET_ALL;
> +	}
> +}
> +EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_setup_xss_caps);
> +
>   static inline void kvm_ops_update(struct kvm_x86_init_ops *ops)
>   {
>   	memcpy(&kvm_x86_ops, ops->runtime_ops, sizeof(kvm_x86_ops));
> @@ -10138,19 +10155,6 @@ int kvm_x86_vendor_init(struct kvm_x86_init_ops *ops)
>   	if (!tdp_enabled)
>   		kvm_caps.supported_quirks &= ~KVM_X86_QUIRK_IGNORE_GUEST_PAT;
>   
> -	if (!kvm_cpu_cap_has(X86_FEATURE_XSAVES))
> -		kvm_caps.supported_xss = 0;
> -
> -	if (!kvm_cpu_cap_has(X86_FEATURE_SHSTK) &&
> -	    !kvm_cpu_cap_has(X86_FEATURE_IBT))
> -		kvm_caps.supported_xss &= ~XFEATURE_MASK_CET_ALL;
> -
> -	if ((kvm_caps.supported_xss & XFEATURE_MASK_CET_ALL) != XFEATURE_MASK_CET_ALL) {
> -		kvm_cpu_cap_clear(X86_FEATURE_SHSTK);
> -		kvm_cpu_cap_clear(X86_FEATURE_IBT);
> -		kvm_caps.supported_xss &= ~XFEATURE_MASK_CET_ALL;
> -	}
> -
>   	if (kvm_caps.has_tsc_control) {
>   		/*
>   		 * Make sure the user can only configure tsc_khz values that
> diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
> index 70e81f008030..94d4f07aaaa0 100644
> --- a/arch/x86/kvm/x86.h
> +++ b/arch/x86/kvm/x86.h
> @@ -483,6 +483,8 @@ extern struct kvm_host_values kvm_host;
>   extern bool enable_pmu;
>   extern bool enable_mediated_pmu;
>   
> +void kvm_setup_xss_caps(void);
> +
>   /*
>    * Get a filtered version of KVM's supported XCR0 that strips out dynamic
>    * features for which the current process doesn't (yet) have permission to use.
Re: [PATCH v2 1/3] KVM: x86: Explicitly configure supported XSS from {svm,vmx}_set_cpu_caps()
Posted by Sean Christopherson 1 week, 3 days ago
On Thu, Jan 29, 2026, Xiaoyao Li wrote:
> On 1/28/2026 9:43 AM, Sean Christopherson wrote:
> > Explicitly configure KVM's supported XSS as part of each vendor's setup
> > flow to fix a bug where clearing SHSTK and IBT in kvm_cpu_caps, e.g. due
> > to lack of CET XFEATURE support, makes kvm-intel.ko unloadable when nested
> > VMX is enabled, i.e. when nested=1.  The late clearing results in
> > nested_vmx_setup_{entry,exit}_ctls() clearing VM_{ENTRY,EXIT}_LOAD_CET_STATE
> > when nested_vmx_setup_ctls_msrs() runs during the CPU compatibility checks,
> > ultimately leading to a mismatched VMCS config due to the reference config
> > having the CET bits set, but every CPU's "local" config having the bits
> > cleared.
> > 
> > Note, kvm_caps.supported_{xcr0,xss} are unconditionally initialized by
> > kvm_x86_vendor_init(), before calling into vendor code, and not referenced
> > between ops->hardware_setup() and their current/old location.
> 
> I'm thinking whether to move the initialization of supported_xss from
> kvm_x86_vendor_init() to kvm_setup_xss_caps(). Anyway it can be a separate
> patch, if we agree to make the change.

Hmm, I definitely don't want to do that, because then we'll end up with asymmetric
initialization of kvm_caps.*, and I don't want to move that initialization under
{svm,vmx}_set_cpu_caps() because it's pretty much guaranteed to lead to different
ordering issues.

One idea would be to call the new API kvm_finalize_xss_caps() instead of
kvm_setup_xss_caps(), but I'm not sure I like that idea.  Or maybe
kvm_constrain_xss_caps()?  That feels awkward and unintuitive though.

All in all, I agree that having a "setup" API rely on prior initialization is a
bit wonky, but I don't love any of the alternatives either. :-/