* [PATCH v2 0/2] KVM: VMX: Handle SEAMCALL or TDCALL VM-Exits
@ 2025-10-16 18:21 Sean Christopherson
2025-10-16 18:21 ` [PATCH v2 1/2] KVM: VMX: Inject #UD if guest tries to execute SEAMCALL or TDCALL Sean Christopherson
` (2 more replies)
0 siblings, 3 replies; 18+ messages in thread
From: Sean Christopherson @ 2025-10-16 18:21 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini
Cc: kvm, linux-kernel, Kai Huang, Xiaoyao Li, Rick Edgecombe,
Dan Williams, Binbin Wu
Add VM-Exit handlers for SEAMCALL and TDCALL as the instructions are gated
only by VMXON, and so a buggy/misbehaving guest will likely be terminated
(because KVM bails with KVM_INTERNAL_ERROR_UNEXPECTED_EXIT_REASON) if the
guest executes SEAMCALL or TDCALL.
v2:
- Apply the behavior only to VMX. KVM can't inject #UDs for TDX, and the
TDX-Module is supposed to handle SEAMCALL. [Chao]
- Fix nested exit handling (inverted return). [Xiaoyao]
- WARN if the TDX-Module punts a SEAMCALL exit to KVM. [Xiaoyao]
- Fix typos. [Binbin]
v1: https://lore.kernel.org/all/20251014231042.1399849-1-seanjc@google.com
Sean Christopherson (2):
KVM: VMX: Inject #UD if guest tries to execute SEAMCALL or TDCALL
KVM: TDX: WARN if a SEAMCALL VM-Exit makes its way out to KVM
arch/x86/include/uapi/asm/vmx.h | 1 +
arch/x86/kvm/vmx/nested.c | 8 ++++++++
arch/x86/kvm/vmx/tdx.c | 3 +++
arch/x86/kvm/vmx/vmx.c | 8 ++++++++
4 files changed, 20 insertions(+)
base-commit: 6b36119b94d0b2bb8cea9d512017efafd461d6ac
--
2.51.0.858.gf9c4a03a3a-goog
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v2 1/2] KVM: VMX: Inject #UD if guest tries to execute SEAMCALL or TDCALL
2025-10-16 18:21 [PATCH v2 0/2] KVM: VMX: Handle SEAMCALL or TDCALL VM-Exits Sean Christopherson
@ 2025-10-16 18:21 ` Sean Christopherson
2025-10-17 2:53 ` Xiaoyao Li
` (3 more replies)
2025-10-16 18:21 ` [PATCH v2 2/2] KVM: TDX: WARN if a SEAMCALL VM-Exit makes its way out to KVM Sean Christopherson
2025-11-04 17:45 ` [PATCH v2 0/2] KVM: VMX: Handle SEAMCALL or TDCALL VM-Exits Sean Christopherson
2 siblings, 4 replies; 18+ messages in thread
From: Sean Christopherson @ 2025-10-16 18:21 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini
Cc: kvm, linux-kernel, Kai Huang, Xiaoyao Li, Rick Edgecombe,
Dan Williams, Binbin Wu
Add VMX exit handlers for SEAMCALL and TDCALL to inject a #UD if a non-TD
guest attempts to execute SEAMCALL or TDCALL. Neither SEAMCALL nor TDCALL
is gated by any software enablement other than VMXON, and so will generate
a VM-Exit instead of e.g. a native #UD when executed from the guest kernel.
Note! No unprivileged DoS of the L1 kernel is possible as TDCALL and
SEAMCALL #GP at CPL > 0, and the CPL check is performed prior to the VMX
non-root (VM-Exit) check, i.e. userspace can't crash the VM. And for a
nested guest, KVM forwards unknown exits to L1, i.e. an L2 kernel can
crash itself, but not L1.
Note #2! The Intel® Trust Domain CPU Architectural Extensions spec's
pseudocode shows the CPL > 0 check for SEAMCALL coming _after_ the VM-Exit,
but that appears to be a documentation bug (likely because the CPL > 0
check was incorrectly bundled with other lower-priority #GP checks).
Testing on SPR and EMR shows that the CPL > 0 check is performed before
the VMX non-root check, i.e. SEAMCALL #GPs when executed in usermode.
Note #3! The aforementioned Trust Domain spec uses confusing pseudocode
that says that SEAMCALL will #UD if executed "inSEAM", but "inSEAM"
specifically means in SEAM Root Mode, i.e. in the TDX-Module. The long-
form description explicitly states that SEAMCALL generates an exit when
executed in "SEAM VMX non-root operation". But that's a moot point as the
TDX-Module injects #UD if the guest attempts to execute SEAMCALL, as
documented in the "Unconditionally Blocked Instructions" section of the
TDX-Module base specification.
Cc: stable@vger.kernel.org
Cc: Kai Huang <kai.huang@intel.com>
Cc: Xiaoyao Li <xiaoyao.li@intel.com>
Cc: Rick Edgecombe <rick.p.edgecombe@intel.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Binbin Wu <binbin.wu@linux.intel.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/include/uapi/asm/vmx.h | 1 +
arch/x86/kvm/vmx/nested.c | 8 ++++++++
arch/x86/kvm/vmx/vmx.c | 8 ++++++++
3 files changed, 17 insertions(+)
diff --git a/arch/x86/include/uapi/asm/vmx.h b/arch/x86/include/uapi/asm/vmx.h
index 9792e329343e..1baa86dfe029 100644
--- a/arch/x86/include/uapi/asm/vmx.h
+++ b/arch/x86/include/uapi/asm/vmx.h
@@ -93,6 +93,7 @@
#define EXIT_REASON_TPAUSE 68
#define EXIT_REASON_BUS_LOCK 74
#define EXIT_REASON_NOTIFY 75
+#define EXIT_REASON_SEAMCALL 76
#define EXIT_REASON_TDCALL 77
#define EXIT_REASON_MSR_READ_IMM 84
#define EXIT_REASON_MSR_WRITE_IMM 85
diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index 76271962cb70..bcea087b642f 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -6728,6 +6728,14 @@ static bool nested_vmx_l1_wants_exit(struct kvm_vcpu *vcpu,
case EXIT_REASON_NOTIFY:
/* Notify VM exit is not exposed to L1 */
return false;
+ case EXIT_REASON_SEAMCALL:
+ case EXIT_REASON_TDCALL:
+ /*
+ * SEAMCALL and TDCALL unconditionally VM-Exit, but aren't
+ * virtualized by KVM for L1 hypervisors, i.e. L1 should
+ * never want or expect such an exit.
+ */
+ return false;
default:
return true;
}
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 546272a5d34d..d1b34b7ca4a3 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -6033,6 +6033,12 @@ static int handle_vmx_instruction(struct kvm_vcpu *vcpu)
return 1;
}
+static int handle_tdx_instruction(struct kvm_vcpu *vcpu)
+{
+ kvm_queue_exception(vcpu, UD_VECTOR);
+ return 1;
+}
+
#ifndef CONFIG_X86_SGX_KVM
static int handle_encls(struct kvm_vcpu *vcpu)
{
@@ -6158,6 +6164,8 @@ static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = {
[EXIT_REASON_ENCLS] = handle_encls,
[EXIT_REASON_BUS_LOCK] = handle_bus_lock_vmexit,
[EXIT_REASON_NOTIFY] = handle_notify,
+ [EXIT_REASON_SEAMCALL] = handle_tdx_instruction,
+ [EXIT_REASON_TDCALL] = handle_tdx_instruction,
[EXIT_REASON_MSR_READ_IMM] = handle_rdmsr_imm,
[EXIT_REASON_MSR_WRITE_IMM] = handle_wrmsr_imm,
};
--
2.51.0.858.gf9c4a03a3a-goog
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v2 2/2] KVM: TDX: WARN if a SEAMCALL VM-Exit makes its way out to KVM
2025-10-16 18:21 [PATCH v2 0/2] KVM: VMX: Handle SEAMCALL or TDCALL VM-Exits Sean Christopherson
2025-10-16 18:21 ` [PATCH v2 1/2] KVM: VMX: Inject #UD if guest tries to execute SEAMCALL or TDCALL Sean Christopherson
@ 2025-10-16 18:21 ` Sean Christopherson
2025-10-17 2:56 ` Xiaoyao Li
` (2 more replies)
2025-11-04 17:45 ` [PATCH v2 0/2] KVM: VMX: Handle SEAMCALL or TDCALL VM-Exits Sean Christopherson
2 siblings, 3 replies; 18+ messages in thread
From: Sean Christopherson @ 2025-10-16 18:21 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini
Cc: kvm, linux-kernel, Kai Huang, Xiaoyao Li, Rick Edgecombe,
Dan Williams, Binbin Wu
WARN if KVM observes a SEAMCALL VM-Exit while running a TD guest, as the
TDX-Module is supposed to inject a #UD, per the "Unconditionally Blocked
Instructions" section of the TDX-Module base specification.
Reported-by: Xiaoyao Li <xiaoyao.li@intel.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/kvm/vmx/tdx.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c
index 097304bf1e1d..ffcfe95f224f 100644
--- a/arch/x86/kvm/vmx/tdx.c
+++ b/arch/x86/kvm/vmx/tdx.c
@@ -2148,6 +2148,9 @@ int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath)
* - If it's not an MSMI, no need to do anything here.
*/
return 1;
+ case EXIT_REASON_SEAMCALL:
+ WARN_ON_ONCE(1);
+ break;
default:
break;
}
--
2.51.0.858.gf9c4a03a3a-goog
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v2 1/2] KVM: VMX: Inject #UD if guest tries to execute SEAMCALL or TDCALL
2025-10-16 18:21 ` [PATCH v2 1/2] KVM: VMX: Inject #UD if guest tries to execute SEAMCALL or TDCALL Sean Christopherson
@ 2025-10-17 2:53 ` Xiaoyao Li
2025-10-17 5:27 ` Binbin Wu
` (2 subsequent siblings)
3 siblings, 0 replies; 18+ messages in thread
From: Xiaoyao Li @ 2025-10-17 2:53 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini
Cc: kvm, linux-kernel, Kai Huang, Rick Edgecombe, Dan Williams,
Binbin Wu
On 10/17/2025 2:21 AM, Sean Christopherson wrote:
> Add VMX exit handlers for SEAMCALL and TDCALL to inject a #UD if a non-TD
> guest attempts to execute SEAMCALL or TDCALL. Neither SEAMCALL nor TDCALL
> is gated by any software enablement other than VMXON, and so will generate
> a VM-Exit instead of e.g. a native #UD when executed from the guest kernel.
>
> Note! No unprivileged DoS of the L1 kernel is possible as TDCALL and
> SEAMCALL #GP at CPL > 0, and the CPL check is performed prior to the VMX
> non-root (VM-Exit) check, i.e. userspace can't crash the VM. And for a
> nested guest, KVM forwards unknown exits to L1, i.e. an L2 kernel can
> crash itself, but not L1.
>
> Note #2! The Intel® Trust Domain CPU Architectural Extensions spec's
> pseudocode shows the CPL > 0 check for SEAMCALL coming _after_ the VM-Exit,
> but that appears to be a documentation bug (likely because the CPL > 0
> check was incorrectly bundled with other lower-priority #GP checks).
> Testing on SPR and EMR shows that the CPL > 0 check is performed before
> the VMX non-root check, i.e. SEAMCALL #GPs when executed in usermode.
>
> Note #3! The aforementioned Trust Domain spec uses confusing pseudocode
> that says that SEAMCALL will #UD if executed "inSEAM", but "inSEAM"
> specifically means in SEAM Root Mode, i.e. in the TDX-Module. The long-
> form description explicitly states that SEAMCALL generates an exit when
> executed in "SEAM VMX non-root operation". But that's a moot point as the
> TDX-Module injects #UD if the guest attempts to execute SEAMCALL, as
> documented in the "Unconditionally Blocked Instructions" section of the
> TDX-Module base specification.
>
> Cc: stable@vger.kernel.org
> Cc: Kai Huang <kai.huang@intel.com>
> Cc: Xiaoyao Li <xiaoyao.li@intel.com>
> Cc: Rick Edgecombe <rick.p.edgecombe@intel.com>
> Cc: Dan Williams <dan.j.williams@intel.com>
> Cc: Binbin Wu <binbin.wu@linux.intel.com>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com>
> ---
> arch/x86/include/uapi/asm/vmx.h | 1 +
> arch/x86/kvm/vmx/nested.c | 8 ++++++++
> arch/x86/kvm/vmx/vmx.c | 8 ++++++++
> 3 files changed, 17 insertions(+)
>
> diff --git a/arch/x86/include/uapi/asm/vmx.h b/arch/x86/include/uapi/asm/vmx.h
> index 9792e329343e..1baa86dfe029 100644
> --- a/arch/x86/include/uapi/asm/vmx.h
> +++ b/arch/x86/include/uapi/asm/vmx.h
> @@ -93,6 +93,7 @@
> #define EXIT_REASON_TPAUSE 68
> #define EXIT_REASON_BUS_LOCK 74
> #define EXIT_REASON_NOTIFY 75
> +#define EXIT_REASON_SEAMCALL 76
> #define EXIT_REASON_TDCALL 77
> #define EXIT_REASON_MSR_READ_IMM 84
> #define EXIT_REASON_MSR_WRITE_IMM 85
> diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
> index 76271962cb70..bcea087b642f 100644
> --- a/arch/x86/kvm/vmx/nested.c
> +++ b/arch/x86/kvm/vmx/nested.c
> @@ -6728,6 +6728,14 @@ static bool nested_vmx_l1_wants_exit(struct kvm_vcpu *vcpu,
> case EXIT_REASON_NOTIFY:
> /* Notify VM exit is not exposed to L1 */
> return false;
> + case EXIT_REASON_SEAMCALL:
> + case EXIT_REASON_TDCALL:
> + /*
> + * SEAMCALL and TDCALL unconditionally VM-Exit, but aren't
> + * virtualized by KVM for L1 hypervisors, i.e. L1 should
> + * never want or expect such an exit.
> + */
> + return false;
> default:
> return true;
> }
> diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
> index 546272a5d34d..d1b34b7ca4a3 100644
> --- a/arch/x86/kvm/vmx/vmx.c
> +++ b/arch/x86/kvm/vmx/vmx.c
> @@ -6033,6 +6033,12 @@ static int handle_vmx_instruction(struct kvm_vcpu *vcpu)
> return 1;
> }
>
> +static int handle_tdx_instruction(struct kvm_vcpu *vcpu)
> +{
> + kvm_queue_exception(vcpu, UD_VECTOR);
> + return 1;
> +}
> +
> #ifndef CONFIG_X86_SGX_KVM
> static int handle_encls(struct kvm_vcpu *vcpu)
> {
> @@ -6158,6 +6164,8 @@ static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = {
> [EXIT_REASON_ENCLS] = handle_encls,
> [EXIT_REASON_BUS_LOCK] = handle_bus_lock_vmexit,
> [EXIT_REASON_NOTIFY] = handle_notify,
> + [EXIT_REASON_SEAMCALL] = handle_tdx_instruction,
> + [EXIT_REASON_TDCALL] = handle_tdx_instruction,
> [EXIT_REASON_MSR_READ_IMM] = handle_rdmsr_imm,
> [EXIT_REASON_MSR_WRITE_IMM] = handle_wrmsr_imm,
> };
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 2/2] KVM: TDX: WARN if a SEAMCALL VM-Exit makes its way out to KVM
2025-10-16 18:21 ` [PATCH v2 2/2] KVM: TDX: WARN if a SEAMCALL VM-Exit makes its way out to KVM Sean Christopherson
@ 2025-10-17 2:56 ` Xiaoyao Li
2025-10-17 5:29 ` Binbin Wu
2025-10-17 10:40 ` Huang, Kai
2 siblings, 0 replies; 18+ messages in thread
From: Xiaoyao Li @ 2025-10-17 2:56 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini
Cc: kvm, linux-kernel, Kai Huang, Rick Edgecombe, Dan Williams,
Binbin Wu
On 10/17/2025 2:21 AM, Sean Christopherson wrote:
> WARN if KVM observes a SEAMCALL VM-Exit while running a TD guest, as the
> TDX-Module is supposed to inject a #UD, per the "Unconditionally Blocked
> Instructions" section of the TDX-Module base specification.
>
> Reported-by: Xiaoyao Li <xiaoyao.li@intel.com>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com>
> ---
> arch/x86/kvm/vmx/tdx.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c
> index 097304bf1e1d..ffcfe95f224f 100644
> --- a/arch/x86/kvm/vmx/tdx.c
> +++ b/arch/x86/kvm/vmx/tdx.c
> @@ -2148,6 +2148,9 @@ int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath)
> * - If it's not an MSMI, no need to do anything here.
> */
> return 1;
> + case EXIT_REASON_SEAMCALL:
> + WARN_ON_ONCE(1);
> + break;
> default:
> break;
> }
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 1/2] KVM: VMX: Inject #UD if guest tries to execute SEAMCALL or TDCALL
2025-10-16 18:21 ` [PATCH v2 1/2] KVM: VMX: Inject #UD if guest tries to execute SEAMCALL or TDCALL Sean Christopherson
2025-10-17 2:53 ` Xiaoyao Li
@ 2025-10-17 5:27 ` Binbin Wu
2025-10-17 10:53 ` Huang, Kai
2025-10-17 20:34 ` Huang, Kai
3 siblings, 0 replies; 18+ messages in thread
From: Binbin Wu @ 2025-10-17 5:27 UTC (permalink / raw)
To: Sean Christopherson
Cc: Paolo Bonzini, kvm, linux-kernel, Kai Huang, Xiaoyao Li,
Rick Edgecombe, Dan Williams
On 10/17/2025 2:21 AM, Sean Christopherson wrote:
> Add VMX exit handlers for SEAMCALL and TDCALL to inject a #UD if a non-TD
> guest attempts to execute SEAMCALL or TDCALL. Neither SEAMCALL nor TDCALL
> is gated by any software enablement other than VMXON, and so will generate
> a VM-Exit instead of e.g. a native #UD when executed from the guest kernel.
>
> Note! No unprivileged DoS of the L1 kernel is possible as TDCALL and
> SEAMCALL #GP at CPL > 0, and the CPL check is performed prior to the VMX
> non-root (VM-Exit) check, i.e. userspace can't crash the VM. And for a
> nested guest, KVM forwards unknown exits to L1, i.e. an L2 kernel can
> crash itself, but not L1.
>
> Note #2! The Intel® Trust Domain CPU Architectural Extensions spec's
> pseudocode shows the CPL > 0 check for SEAMCALL coming _after_ the VM-Exit,
> but that appears to be a documentation bug (likely because the CPL > 0
> check was incorrectly bundled with other lower-priority #GP checks).
> Testing on SPR and EMR shows that the CPL > 0 check is performed before
> the VMX non-root check, i.e. SEAMCALL #GPs when executed in usermode.
>
> Note #3! The aforementioned Trust Domain spec uses confusing pseudocode
> that says that SEAMCALL will #UD if executed "inSEAM", but "inSEAM"
> specifically means in SEAM Root Mode, i.e. in the TDX-Module. The long-
> form description explicitly states that SEAMCALL generates an exit when
> executed in "SEAM VMX non-root operation". But that's a moot point as the
> TDX-Module injects #UD if the guest attempts to execute SEAMCALL, as
> documented in the "Unconditionally Blocked Instructions" section of the
> TDX-Module base specification.
>
> Cc: stable@vger.kernel.org
> Cc: Kai Huang <kai.huang@intel.com>
> Cc: Xiaoyao Li <xiaoyao.li@intel.com>
> Cc: Rick Edgecombe <rick.p.edgecombe@intel.com>
> Cc: Dan Williams <dan.j.williams@intel.com>
> Cc: Binbin Wu <binbin.wu@linux.intel.com>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
Reviewed-by: Binbin Wu <binbin.wu@linux.intel.com>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 2/2] KVM: TDX: WARN if a SEAMCALL VM-Exit makes its way out to KVM
2025-10-16 18:21 ` [PATCH v2 2/2] KVM: TDX: WARN if a SEAMCALL VM-Exit makes its way out to KVM Sean Christopherson
2025-10-17 2:56 ` Xiaoyao Li
@ 2025-10-17 5:29 ` Binbin Wu
2025-10-17 10:40 ` Huang, Kai
2 siblings, 0 replies; 18+ messages in thread
From: Binbin Wu @ 2025-10-17 5:29 UTC (permalink / raw)
To: Sean Christopherson
Cc: Paolo Bonzini, kvm, linux-kernel, Kai Huang, Xiaoyao Li,
Rick Edgecombe, Dan Williams
On 10/17/2025 2:21 AM, Sean Christopherson wrote:
> WARN if KVM observes a SEAMCALL VM-Exit while running a TD guest, as the
> TDX-Module is supposed to inject a #UD, per the "Unconditionally Blocked
> Instructions" section of the TDX-Module base specification.
>
> Reported-by: Xiaoyao Li <xiaoyao.li@intel.com>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
Reviewed-by: Binbin Wu <binbin.wu@linux.intel.com>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 2/2] KVM: TDX: WARN if a SEAMCALL VM-Exit makes its way out to KVM
2025-10-16 18:21 ` [PATCH v2 2/2] KVM: TDX: WARN if a SEAMCALL VM-Exit makes its way out to KVM Sean Christopherson
2025-10-17 2:56 ` Xiaoyao Li
2025-10-17 5:29 ` Binbin Wu
@ 2025-10-17 10:40 ` Huang, Kai
2025-10-17 17:25 ` Sean Christopherson
2 siblings, 1 reply; 18+ messages in thread
From: Huang, Kai @ 2025-10-17 10:40 UTC (permalink / raw)
To: pbonzini@redhat.com, seanjc@google.com
Cc: Li, Xiaoyao, kvm@vger.kernel.org, Williams, Dan J,
linux-kernel@vger.kernel.org, Edgecombe, Rick P,
binbin.wu@linux.intel.com
On Thu, 2025-10-16 at 11:21 -0700, Sean Christopherson wrote:
> WARN if KVM observes a SEAMCALL VM-Exit while running a TD guest, as the
> TDX-Module is supposed to inject a #UD, per the "Unconditionally Blocked
> Instructions" section of the TDX-Module base specification.
>
> Reported-by: Xiaoyao Li <xiaoyao.li@intel.com>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
> arch/x86/kvm/vmx/tdx.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c
> index 097304bf1e1d..ffcfe95f224f 100644
> --- a/arch/x86/kvm/vmx/tdx.c
> +++ b/arch/x86/kvm/vmx/tdx.c
> @@ -2148,6 +2148,9 @@ int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath)
> * - If it's not an MSMI, no need to do anything here.
> */
> return 1;
> + case EXIT_REASON_SEAMCALL:
> + WARN_ON_ONCE(1);
> + break;
>
While this exit should never happen from a TDX guest, I am wondering why
we need to explicitly handle the SEAMCALL? E.g., per "Unconditionally
Blocked Instructions" ENCLS/ENCLV are also listed, therefore
EXIT_REASON_ELCLS/ENCLV should never come from a TDX guest either.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 1/2] KVM: VMX: Inject #UD if guest tries to execute SEAMCALL or TDCALL
2025-10-16 18:21 ` [PATCH v2 1/2] KVM: VMX: Inject #UD if guest tries to execute SEAMCALL or TDCALL Sean Christopherson
2025-10-17 2:53 ` Xiaoyao Li
2025-10-17 5:27 ` Binbin Wu
@ 2025-10-17 10:53 ` Huang, Kai
2025-10-17 13:00 ` Sean Christopherson
2025-10-17 20:34 ` Huang, Kai
3 siblings, 1 reply; 18+ messages in thread
From: Huang, Kai @ 2025-10-17 10:53 UTC (permalink / raw)
To: pbonzini@redhat.com, seanjc@google.com
Cc: Li, Xiaoyao, kvm@vger.kernel.org, Williams, Dan J,
linux-kernel@vger.kernel.org, Edgecombe, Rick P,
binbin.wu@linux.intel.com
> --- a/arch/x86/kvm/vmx/nested.c
> +++ b/arch/x86/kvm/vmx/nested.c
> @@ -6728,6 +6728,14 @@ static bool nested_vmx_l1_wants_exit(struct kvm_vcpu *vcpu,
> case EXIT_REASON_NOTIFY:
> /* Notify VM exit is not exposed to L1 */
> return false;
> + case EXIT_REASON_SEAMCALL:
> + case EXIT_REASON_TDCALL:
> + /*
> + * SEAMCALL and TDCALL unconditionally VM-Exit, but aren't
> + * virtualized by KVM for L1 hypervisors, i.e. L1 should
> + * never want or expect such an exit.
> + */
> + return false;
Sorry for commenting late.
I think from emulating hardware behaviour's perspective, if L1 doesn't
support TDX (obviously true), SEAMCALL/TDCALL in L2 should cause VMEXIT to
L1. In other words, L1 is expecting a VMEXIT in such case. Whether L1
can handle such VMEXIT is another story -- it may inject a #UD to L2 or
may not (similar to the current upstream KVM), but it is L1's
responsibility.
So I think while this patch certainly honors the correct behaviour for L2,
it doesn't honor for L1. But I think ultimately L1 should be the one who
is responsible for emulating hardware behaviour for L2.
E.g., assuming we have a KVM selftest in L1 to test SEAMCALL/TDCALL in
normal VMX L2. L1 should be able to catch it's own bug when such VMEXIT
isn't handled correctly. But with this patch, L1 will never be able to
catch this IIUC.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 1/2] KVM: VMX: Inject #UD if guest tries to execute SEAMCALL or TDCALL
2025-10-17 10:53 ` Huang, Kai
@ 2025-10-17 13:00 ` Sean Christopherson
2025-10-17 20:34 ` Huang, Kai
0 siblings, 1 reply; 18+ messages in thread
From: Sean Christopherson @ 2025-10-17 13:00 UTC (permalink / raw)
To: Kai Huang
Cc: pbonzini@redhat.com, Xiaoyao Li, kvm@vger.kernel.org,
Dan J Williams, linux-kernel@vger.kernel.org, Rick P Edgecombe,
binbin.wu@linux.intel.com
On Fri, Oct 17, 2025, Kai Huang wrote:
>
> > --- a/arch/x86/kvm/vmx/nested.c
> > +++ b/arch/x86/kvm/vmx/nested.c
> > @@ -6728,6 +6728,14 @@ static bool nested_vmx_l1_wants_exit(struct kvm_vcpu *vcpu,
> > case EXIT_REASON_NOTIFY:
> > /* Notify VM exit is not exposed to L1 */
> > return false;
> > + case EXIT_REASON_SEAMCALL:
> > + case EXIT_REASON_TDCALL:
> > + /*
> > + * SEAMCALL and TDCALL unconditionally VM-Exit, but aren't
> > + * virtualized by KVM for L1 hypervisors, i.e. L1 should
> > + * never want or expect such an exit.
> > + */
> > + return false;
>
> Sorry for commenting late.
>
> I think from emulating hardware behaviour's perspective, if L1 doesn't
> support TDX (obviously true), SEAMCALL/TDCALL in L2 should cause VMEXIT to
> L1. In other words, L1 is expecting a VMEXIT in such case.
No, because from L1's perspective, the opcodes map to undefined instructions and
thus should #UD in L2. There's no super explicit enumeration, but IMO it's fair
to say that for L1 to think the instructions exists, it would need to observe
IA32_SEAMRR_PHYS_{BASE,MASK} for SEAMCALL, and MSR_IA32_MKTME_KEYID_PARTITIONING
as well for TDCALL. KVM doesn't emulate any of those instructions, and so L1
should never expect SEAMCALL or TDCALL to do anything other than #UD.
> Whether L1 can handle such VMEXIT is another story -- it may inject a #UD to
> L2 or may not (similar to the current upstream KVM), but it is L1's
> responsibility.
>
> So I think while this patch certainly honors the correct behaviour for L2,
> it doesn't honor for L1. But I think ultimately L1 should be the one who
> is responsible for emulating hardware behaviour for L2.
>
> E.g., assuming we have a KVM selftest in L1 to test SEAMCALL/TDCALL in
> normal VMX L2. L1 should be able to catch it's own bug when such VMEXIT
> isn't handled correctly. But with this patch, L1 will never be able to
> catch this IIUC.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 2/2] KVM: TDX: WARN if a SEAMCALL VM-Exit makes its way out to KVM
2025-10-17 10:40 ` Huang, Kai
@ 2025-10-17 17:25 ` Sean Christopherson
2025-10-17 20:58 ` Huang, Kai
0 siblings, 1 reply; 18+ messages in thread
From: Sean Christopherson @ 2025-10-17 17:25 UTC (permalink / raw)
To: Kai Huang
Cc: pbonzini@redhat.com, Xiaoyao Li, kvm@vger.kernel.org,
Dan J Williams, linux-kernel@vger.kernel.org, Rick P Edgecombe,
binbin.wu@linux.intel.com
On Fri, Oct 17, 2025, Kai Huang wrote:
> On Thu, 2025-10-16 at 11:21 -0700, Sean Christopherson wrote:
> > WARN if KVM observes a SEAMCALL VM-Exit while running a TD guest, as the
> > TDX-Module is supposed to inject a #UD, per the "Unconditionally Blocked
> > Instructions" section of the TDX-Module base specification.
> >
> > Reported-by: Xiaoyao Li <xiaoyao.li@intel.com>
> > Signed-off-by: Sean Christopherson <seanjc@google.com>
> > ---
> > arch/x86/kvm/vmx/tdx.c | 3 +++
> > 1 file changed, 3 insertions(+)
> >
> > diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c
> > index 097304bf1e1d..ffcfe95f224f 100644
> > --- a/arch/x86/kvm/vmx/tdx.c
> > +++ b/arch/x86/kvm/vmx/tdx.c
> > @@ -2148,6 +2148,9 @@ int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath)
> > * - If it's not an MSMI, no need to do anything here.
> > */
> > return 1;
> > + case EXIT_REASON_SEAMCALL:
> > + WARN_ON_ONCE(1);
> > + break;
> >
>
> While this exit should never happen from a TDX guest, I am wondering why
> we need to explicitly handle the SEAMCALL? E.g., per "Unconditionally
> Blocked Instructions" ENCLS/ENCLV are also listed, therefore
> EXIT_REASON_ELCLS/ENCLV should never come from a TDX guest either.
Good point. SEAMCALL was obviously top of mind, I didn't think about all the
other exits that should be impossible.
I haven't looked closely, at all, but I wonder if we can get away with this?
diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c
index 097304bf1e1d..4c68444bd673 100644
--- a/arch/x86/kvm/vmx/tdx.c
+++ b/arch/x86/kvm/vmx/tdx.c
@@ -2149,6 +2149,8 @@ int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath)
*/
return 1;
default:
+ /* All other known exits should be handled by the TDX-Module. */
+ WARN_ON_ONCE(exit_reason.basic <= EXIT_REASON_TDCALL);
break;
}
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v2 1/2] KVM: VMX: Inject #UD if guest tries to execute SEAMCALL or TDCALL
2025-10-17 13:00 ` Sean Christopherson
@ 2025-10-17 20:34 ` Huang, Kai
0 siblings, 0 replies; 18+ messages in thread
From: Huang, Kai @ 2025-10-17 20:34 UTC (permalink / raw)
To: seanjc@google.com
Cc: Li, Xiaoyao, kvm@vger.kernel.org, pbonzini@redhat.com,
Williams, Dan J, linux-kernel@vger.kernel.org, Edgecombe, Rick P,
binbin.wu@linux.intel.com
On Fri, 2025-10-17 at 06:00 -0700, Sean Christopherson wrote:
> On Fri, Oct 17, 2025, Kai Huang wrote:
> >
> > > --- a/arch/x86/kvm/vmx/nested.c
> > > +++ b/arch/x86/kvm/vmx/nested.c
> > > @@ -6728,6 +6728,14 @@ static bool nested_vmx_l1_wants_exit(struct kvm_vcpu *vcpu,
> > > case EXIT_REASON_NOTIFY:
> > > /* Notify VM exit is not exposed to L1 */
> > > return false;
> > > + case EXIT_REASON_SEAMCALL:
> > > + case EXIT_REASON_TDCALL:
> > > + /*
> > > + * SEAMCALL and TDCALL unconditionally VM-Exit, but aren't
> > > + * virtualized by KVM for L1 hypervisors, i.e. L1 should
> > > + * never want or expect such an exit.
> > > + */
> > > + return false;
> >
> > Sorry for commenting late.
> >
> > I think from emulating hardware behaviour's perspective, if L1 doesn't
> > support TDX (obviously true), SEAMCALL/TDCALL in L2 should cause VMEXIT to
> > L1. In other words, L1 is expecting a VMEXIT in such case.
>
> No, because from L1's perspective, the opcodes map to undefined instructions and
> thus should #UD in L2. There's no super explicit enumeration, but IMO it's fair
> to say that for L1 to think the instructions exists, it would need to observe
> IA32_SEAMRR_PHYS_{BASE,MASK} for SEAMCALL, and MSR_IA32_MKTME_KEYID_PARTITIONING
> as well for TDCALL. KVM doesn't emulate any of those instructions, and so L1
> should never expect SEAMCALL or TDCALL to do anything other than #UD.
>
Oh right. I forgot the SEAMCALL/TDCALL VMEXIT only happens on TDX-capable
machine. :-)
>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 1/2] KVM: VMX: Inject #UD if guest tries to execute SEAMCALL or TDCALL
2025-10-16 18:21 ` [PATCH v2 1/2] KVM: VMX: Inject #UD if guest tries to execute SEAMCALL or TDCALL Sean Christopherson
` (2 preceding siblings ...)
2025-10-17 10:53 ` Huang, Kai
@ 2025-10-17 20:34 ` Huang, Kai
3 siblings, 0 replies; 18+ messages in thread
From: Huang, Kai @ 2025-10-17 20:34 UTC (permalink / raw)
To: pbonzini@redhat.com, seanjc@google.com
Cc: Li, Xiaoyao, kvm@vger.kernel.org, Williams, Dan J,
linux-kernel@vger.kernel.org, Edgecombe, Rick P,
binbin.wu@linux.intel.com
On Thu, 2025-10-16 at 11:21 -0700, Sean Christopherson wrote:
> Add VMX exit handlers for SEAMCALL and TDCALL to inject a #UD if a non-TD
> guest attempts to execute SEAMCALL or TDCALL. Neither SEAMCALL nor TDCALL
> is gated by any software enablement other than VMXON, and so will generate
> a VM-Exit instead of e.g. a native #UD when executed from the guest kernel.
>
> Note! No unprivileged DoS of the L1 kernel is possible as TDCALL and
> SEAMCALL #GP at CPL > 0, and the CPL check is performed prior to the VMX
> non-root (VM-Exit) check, i.e. userspace can't crash the VM. And for a
> nested guest, KVM forwards unknown exits to L1, i.e. an L2 kernel can
> crash itself, but not L1.
>
> Note #2! The Intel® Trust Domain CPU Architectural Extensions spec's
> pseudocode shows the CPL > 0 check for SEAMCALL coming _after_ the VM-Exit,
> but that appears to be a documentation bug (likely because the CPL > 0
> check was incorrectly bundled with other lower-priority #GP checks).
> Testing on SPR and EMR shows that the CPL > 0 check is performed before
> the VMX non-root check, i.e. SEAMCALL #GPs when executed in usermode.
>
> Note #3! The aforementioned Trust Domain spec uses confusing pseudocode
> that says that SEAMCALL will #UD if executed "inSEAM", but "inSEAM"
> specifically means in SEAM Root Mode, i.e. in the TDX-Module. The long-
> form description explicitly states that SEAMCALL generates an exit when
> executed in "SEAM VMX non-root operation". But that's a moot point as the
> TDX-Module injects #UD if the guest attempts to execute SEAMCALL, as
> documented in the "Unconditionally Blocked Instructions" section of the
> TDX-Module base specification.
>
> Cc: stable@vger.kernel.org
> Cc: Kai Huang <kai.huang@intel.com>
> Cc: Xiaoyao Li <xiaoyao.li@intel.com>
> Cc: Rick Edgecombe <rick.p.edgecombe@intel.com>
> Cc: Dan Williams <dan.j.williams@intel.com>
> Cc: Binbin Wu <binbin.wu@linux.intel.com>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
>
Reviewed-by: Kai Huang <kai.huang@intel.com>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 2/2] KVM: TDX: WARN if a SEAMCALL VM-Exit makes its way out to KVM
2025-10-17 17:25 ` Sean Christopherson
@ 2025-10-17 20:58 ` Huang, Kai
2025-10-17 21:11 ` Huang, Kai
2025-10-20 6:10 ` Xiaoyao Li
0 siblings, 2 replies; 18+ messages in thread
From: Huang, Kai @ 2025-10-17 20:58 UTC (permalink / raw)
To: seanjc@google.com
Cc: Li, Xiaoyao, kvm@vger.kernel.org, pbonzini@redhat.com,
Williams, Dan J, linux-kernel@vger.kernel.org, Edgecombe, Rick P,
binbin.wu@linux.intel.com
On Fri, 2025-10-17 at 10:25 -0700, Sean Christopherson wrote:
> On Fri, Oct 17, 2025, Kai Huang wrote:
> > On Thu, 2025-10-16 at 11:21 -0700, Sean Christopherson wrote:
> > > WARN if KVM observes a SEAMCALL VM-Exit while running a TD guest, as the
> > > TDX-Module is supposed to inject a #UD, per the "Unconditionally Blocked
> > > Instructions" section of the TDX-Module base specification.
> > >
> > > Reported-by: Xiaoyao Li <xiaoyao.li@intel.com>
> > > Signed-off-by: Sean Christopherson <seanjc@google.com>
> > > ---
> > > arch/x86/kvm/vmx/tdx.c | 3 +++
> > > 1 file changed, 3 insertions(+)
> > >
> > > diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c
> > > index 097304bf1e1d..ffcfe95f224f 100644
> > > --- a/arch/x86/kvm/vmx/tdx.c
> > > +++ b/arch/x86/kvm/vmx/tdx.c
> > > @@ -2148,6 +2148,9 @@ int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath)
> > > * - If it's not an MSMI, no need to do anything here.
> > > */
> > > return 1;
> > > + case EXIT_REASON_SEAMCALL:
> > > + WARN_ON_ONCE(1);
> > > + break;
> > >
> >
> > While this exit should never happen from a TDX guest, I am wondering why
> > we need to explicitly handle the SEAMCALL? E.g., per "Unconditionally
> > Blocked Instructions" ENCLS/ENCLV are also listed, therefore
> > EXIT_REASON_ELCLS/ENCLV should never come from a TDX guest either.
>
> Good point. SEAMCALL was obviously top of mind, I didn't think about all the
> other exits that should be impossible.
>
> I haven't looked closely, at all, but I wonder if we can get away with this?
>
> diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c
> index 097304bf1e1d..4c68444bd673 100644
> --- a/arch/x86/kvm/vmx/tdx.c
> +++ b/arch/x86/kvm/vmx/tdx.c
> @@ -2149,6 +2149,8 @@ int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath)
> */
> return 1;
> default:
> + /* All other known exits should be handled by the TDX-Module. */
> + WARN_ON_ONCE(exit_reason.basic <= c);
> break;
> }
Not 100% sure, but should be fine? Needs more second eyes here.
E.g., when a new module feature makes another exit reason possible then
presumably we need explicit opt-in to that feature.
Don't quite follow 'exit_reason.basic <= c' part, though. Maybe we can
just unconditional WARN_ON_ONCE()?
Or we can do things similar to VMX:
vcpu_unimpl(vcpu, "vmx: unexpected exit reason 0x%x\n",
exit_reason.full);
Or just get rid of this patch :-)
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 2/2] KVM: TDX: WARN if a SEAMCALL VM-Exit makes its way out to KVM
2025-10-17 20:58 ` Huang, Kai
@ 2025-10-17 21:11 ` Huang, Kai
2025-10-20 6:10 ` Xiaoyao Li
1 sibling, 0 replies; 18+ messages in thread
From: Huang, Kai @ 2025-10-17 21:11 UTC (permalink / raw)
To: seanjc@google.com
Cc: Li, Xiaoyao, kvm@vger.kernel.org, pbonzini@redhat.com,
Williams, Dan J, linux-kernel@vger.kernel.org, Edgecombe, Rick P,
binbin.wu@linux.intel.com
On Sat, 2025-10-18 at 09:58 +1300, Kai Huang wrote:
> On Fri, 2025-10-17 at 10:25 -0700, Sean Christopherson wrote:
> > On Fri, Oct 17, 2025, Kai Huang wrote:
> > > On Thu, 2025-10-16 at 11:21 -0700, Sean Christopherson wrote:
> > > > WARN if KVM observes a SEAMCALL VM-Exit while running a TD guest, as the
> > > > TDX-Module is supposed to inject a #UD, per the "Unconditionally Blocked
> > > > Instructions" section of the TDX-Module base specification.
> > > >
> > > > Reported-by: Xiaoyao Li <xiaoyao.li@intel.com>
> > > > Signed-off-by: Sean Christopherson <seanjc@google.com>
> > > > ---
> > > > arch/x86/kvm/vmx/tdx.c | 3 +++
> > > > 1 file changed, 3 insertions(+)
> > > >
> > > > diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c
> > > > index 097304bf1e1d..ffcfe95f224f 100644
> > > > --- a/arch/x86/kvm/vmx/tdx.c
> > > > +++ b/arch/x86/kvm/vmx/tdx.c
> > > > @@ -2148,6 +2148,9 @@ int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath)
> > > > * - If it's not an MSMI, no need to do anything here.
> > > > */
> > > > return 1;
> > > > + case EXIT_REASON_SEAMCALL:
> > > > + WARN_ON_ONCE(1);
> > > > + break;
> > > >
> > >
> > > While this exit should never happen from a TDX guest, I am wondering why
> > > we need to explicitly handle the SEAMCALL? E.g., per "Unconditionally
> > > Blocked Instructions" ENCLS/ENCLV are also listed, therefore
> > > EXIT_REASON_ELCLS/ENCLV should never come from a TDX guest either.
> >
> > Good point. SEAMCALL was obviously top of mind, I didn't think about all the
> > other exits that should be impossible.
> >
> > I haven't looked closely, at all, but I wonder if we can get away with this?
> >
> > diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c
> > index 097304bf1e1d..4c68444bd673 100644
> > --- a/arch/x86/kvm/vmx/tdx.c
> > +++ b/arch/x86/kvm/vmx/tdx.c
> > @@ -2149,6 +2149,8 @@ int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath)
> > */
> > return 1;
> > default:
> > + /* All other known exits should be handled by the TDX-Module. */
> > + WARN_ON_ONCE(exit_reason.basic <= c);
Sorry somehow I clobbered the text (at Saturday morning):
WARN_ON_ONCE(exit_reason.basic <= EXIT_REASON_TDCALL);
> > break;
> > }
>
> Not 100% sure, but should be fine? Needs more second eyes here.
>
> E.g., when a new module feature makes another exit reason possible then
> presumably we need explicit opt-in to that feature.
>
> Don't quite follow 'exit_reason.basic <= c' part, though. Maybe we can
> just unconditional WARN_ON_ONCE()?
... and copied here..
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 2/2] KVM: TDX: WARN if a SEAMCALL VM-Exit makes its way out to KVM
2025-10-17 20:58 ` Huang, Kai
2025-10-17 21:11 ` Huang, Kai
@ 2025-10-20 6:10 ` Xiaoyao Li
2025-10-20 15:03 ` Sean Christopherson
1 sibling, 1 reply; 18+ messages in thread
From: Xiaoyao Li @ 2025-10-20 6:10 UTC (permalink / raw)
To: Huang, Kai, seanjc@google.com
Cc: kvm@vger.kernel.org, pbonzini@redhat.com, Williams, Dan J,
linux-kernel@vger.kernel.org, Edgecombe, Rick P,
binbin.wu@linux.intel.com
On 10/18/2025 4:58 AM, Huang, Kai wrote:
> On Fri, 2025-10-17 at 10:25 -0700, Sean Christopherson wrote:
>> On Fri, Oct 17, 2025, Kai Huang wrote:
>>> On Thu, 2025-10-16 at 11:21 -0700, Sean Christopherson wrote:
>>>> WARN if KVM observes a SEAMCALL VM-Exit while running a TD guest, as the
>>>> TDX-Module is supposed to inject a #UD, per the "Unconditionally Blocked
>>>> Instructions" section of the TDX-Module base specification.
>>>>
>>>> Reported-by: Xiaoyao Li <xiaoyao.li@intel.com>
>>>> Signed-off-by: Sean Christopherson <seanjc@google.com>
>>>> ---
>>>> arch/x86/kvm/vmx/tdx.c | 3 +++
>>>> 1 file changed, 3 insertions(+)
>>>>
>>>> diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c
>>>> index 097304bf1e1d..ffcfe95f224f 100644
>>>> --- a/arch/x86/kvm/vmx/tdx.c
>>>> +++ b/arch/x86/kvm/vmx/tdx.c
>>>> @@ -2148,6 +2148,9 @@ int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath)
>>>> * - If it's not an MSMI, no need to do anything here.
>>>> */
>>>> return 1;
>>>> + case EXIT_REASON_SEAMCALL:
>>>> + WARN_ON_ONCE(1);
>>>> + break;
>>>>
>>>
>>> While this exit should never happen from a TDX guest, I am wondering why
>>> we need to explicitly handle the SEAMCALL? E.g., per "Unconditionally
>>> Blocked Instructions" ENCLS/ENCLV are also listed, therefore
>>> EXIT_REASON_ELCLS/ENCLV should never come from a TDX guest either.
>>
>> Good point. SEAMCALL was obviously top of mind, I didn't think about all the
>> other exits that should be impossible.
>>
>> I haven't looked closely, at all, but I wonder if we can get away with this?
>>
>> diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c
>> index 097304bf1e1d..4c68444bd673 100644
>> --- a/arch/x86/kvm/vmx/tdx.c
>> +++ b/arch/x86/kvm/vmx/tdx.c
>> @@ -2149,6 +2149,8 @@ int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath)
>> */
>> return 1;
>> default:
>> + /* All other known exits should be handled by the TDX-Module. */
>> + WARN_ON_ONCE(exit_reason.basic <= c);
>> break;
>> }
>
> Not 100% sure, but should be fine? Needs more second eyes here.
>
> E.g., when a new module feature makes another exit reason possible then
> presumably we need explicit opt-in to that feature.
>
> Don't quite follow 'exit_reason.basic <= c' part, though. Maybe we can
> just unconditional WARN_ON_ONCE()?
>
> Or we can do things similar to VMX:
>
> vcpu_unimpl(vcpu, "vmx: unexpected exit reason 0x%x\n",
> exit_reason.full);
>
> Or just get rid of this patch :-)
I agree to it.
WARN_ON_ONCE() seems not provide more information except that we can
identify quickly there is TDX module bug when it gets hit.
But it's not too hard to get these information from the
KVM_INTERNAL_ERROR_UNEXPECTED_EXIT_REASON with vp_enter_ret in data[0].
And if we add WARN_ON_ONCE() here, we need to evaluate if it needs to
update "EXIT_REASON_TDCALL" everytime a new EXIT reason is introduced.
e.g., currently the largest exit reason number defined in SDM is 79 (for
WRMSRLIST) and it is actually handled by TDX module and KVM cannot
receive it from a TD vcpu.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 2/2] KVM: TDX: WARN if a SEAMCALL VM-Exit makes its way out to KVM
2025-10-20 6:10 ` Xiaoyao Li
@ 2025-10-20 15:03 ` Sean Christopherson
0 siblings, 0 replies; 18+ messages in thread
From: Sean Christopherson @ 2025-10-20 15:03 UTC (permalink / raw)
To: Xiaoyao Li
Cc: Kai Huang, kvm@vger.kernel.org, pbonzini@redhat.com,
Dan J Williams, linux-kernel@vger.kernel.org, Rick P Edgecombe,
binbin.wu@linux.intel.com
On Mon, Oct 20, 2025, Xiaoyao Li wrote:
> On 10/18/2025 4:58 AM, Huang, Kai wrote:
> > On Fri, 2025-10-17 at 10:25 -0700, Sean Christopherson wrote:
> > > On Fri, Oct 17, 2025, Kai Huang wrote:
> > > > While this exit should never happen from a TDX guest, I am wondering why
> > > > we need to explicitly handle the SEAMCALL? E.g., per "Unconditionally
> > > > Blocked Instructions" ENCLS/ENCLV are also listed, therefore
> > > > EXIT_REASON_ELCLS/ENCLV should never come from a TDX guest either.
> > >
> > > Good point. SEAMCALL was obviously top of mind, I didn't think about all the
> > > other exits that should be impossible.
> > >
> > > I haven't looked closely, at all, but I wonder if we can get away with this?
> > >
> > > diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c
> > > index 097304bf1e1d..4c68444bd673 100644
> > > --- a/arch/x86/kvm/vmx/tdx.c
> > > +++ b/arch/x86/kvm/vmx/tdx.c
> > > @@ -2149,6 +2149,8 @@ int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath)
> > > */
> > > return 1;
> > > default:
> > > + /* All other known exits should be handled by the TDX-Module. */
> > > + WARN_ON_ONCE(exit_reason.basic <= c);
> > > break;
> > > }
> >
> > Not 100% sure, but should be fine? Needs more second eyes here.
> >
> > E.g., when a new module feature makes another exit reason possible then
> > presumably we need explicit opt-in to that feature.
> >
> > Don't quite follow 'exit_reason.basic <= c' part, though. Maybe we can
> > just unconditional WARN_ON_ONCE()?
> >
> > Or we can do things similar to VMX:
> >
> > vcpu_unimpl(vcpu, "vmx: unexpected exit reason 0x%x\n",
> > exit_reason.full);
> >
> > Or just get rid of this patch :-)
>
> I agree to it.
>
> WARN_ON_ONCE() seems not provide more information except that we can
> identify quickly there is TDX module bug when it gets hit.
WARNs are helpful for fuzzing, e.g. with syzkaller, where userspace isn't going
to complain or even log anything if KVM_RUN fails.
> But it's not too hard to get these information from the
> KVM_INTERNAL_ERROR_UNEXPECTED_EXIT_REASON with vp_enter_ret in data[0].
>
> And if we add WARN_ON_ONCE() here, we need to evaluate if it needs to update
> "EXIT_REASON_TDCALL" everytime a new EXIT reason is introduced.
> e.g., currently the largest exit reason number defined in SDM is 79 (for
> WRMSRLIST) and it is actually handled by TDX module and KVM cannot receive
> it from a TD vcpu.
Hmm, to some extent this is a case of "don't let perfect be the enemy of good
enough". Just because we can't WARN on _all_ unexpected exits doesn't make
WARNing on the others useless.
That said, I agree that making the WARN conditional on the exit reason would be
a maintenance burden. And I also agree with the implied "rule" that TDX should
follow whatever VMX is doing (and ideally SVM would behavior identically as well).
At the very least, we should consolidate that code. And then we can have a broader
discussion on how exactly to add a WARN. E.g. if for some reason we can't WARN
unconditionally, we could add an off-by-default module param.
I'll drop this patch and post a mini-series with the below to start a general
conversation on whether or not to WARN on unexpected exits.
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 48598d017d6f..4fbe4b7ce1da 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -2167,6 +2167,7 @@ void __kvm_prepare_emulation_failure_exit(struct kvm_vcpu *vcpu,
void kvm_prepare_emulation_failure_exit(struct kvm_vcpu *vcpu);
void kvm_prepare_event_vectoring_exit(struct kvm_vcpu *vcpu, gpa_t gpa);
+void kvm_prepare_unexpected_reason_exit(struct kvm_vcpu *vcpu, u64 exit_reason);
void kvm_enable_efer_bits(u64);
bool kvm_valid_efer(struct kvm_vcpu *vcpu, u64 efer);
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index f14709a511aa..83e0d4d5f4c5 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -3451,13 +3451,8 @@ static bool svm_check_exit_valid(u64 exit_code)
static int svm_handle_invalid_exit(struct kvm_vcpu *vcpu, u64 exit_code)
{
- vcpu_unimpl(vcpu, "svm: unexpected exit reason 0x%llx\n", exit_code);
dump_vmcb(vcpu);
- vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
- vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_UNEXPECTED_EXIT_REASON;
- vcpu->run->internal.ndata = 2;
- vcpu->run->internal.data[0] = exit_code;
- vcpu->run->internal.data[1] = vcpu->arch.last_vmentry_cpu;
+ kvm_prepare_unexpected_reason_exit(vcpu, exit_code);
return 0;
}
diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c
index 326db9b9c567..079d9f13eddb 100644
--- a/arch/x86/kvm/vmx/tdx.c
+++ b/arch/x86/kvm/vmx/tdx.c
@@ -2145,11 +2145,7 @@ int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath)
}
unhandled_exit:
- vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
- vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_UNEXPECTED_EXIT_REASON;
- vcpu->run->internal.ndata = 2;
- vcpu->run->internal.data[0] = vp_enter_ret;
- vcpu->run->internal.data[1] = vcpu->arch.last_vmentry_cpu;
+ kvm_prepare_unexpected_reason_exit(vcpu, vp_enter_ret);
return 0;
}
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 1021d3b65ea0..08f7957ed4c3 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -6642,15 +6642,8 @@ static int __vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)
return kvm_vmx_exit_handlers[exit_handler_index](vcpu);
unexpected_vmexit:
- vcpu_unimpl(vcpu, "vmx: unexpected exit reason 0x%x\n",
- exit_reason.full);
dump_vmcs(vcpu);
- vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
- vcpu->run->internal.suberror =
- KVM_INTERNAL_ERROR_UNEXPECTED_EXIT_REASON;
- vcpu->run->internal.ndata = 2;
- vcpu->run->internal.data[0] = exit_reason.full;
- vcpu->run->internal.data[1] = vcpu->arch.last_vmentry_cpu;
+ kvm_prepare_unexpected_reason_exit(vcpu, exit_reason.full);
return 0;
}
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index b4b5d2d09634..c826cd05228a 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -9110,6 +9110,18 @@ void kvm_prepare_event_vectoring_exit(struct kvm_vcpu *vcpu, gpa_t gpa)
}
EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_prepare_event_vectoring_exit);
+void kvm_prepare_unexpected_reason_exit(struct kvm_vcpu *vcpu, u64 exit_reason)
+{
+ vcpu_unimpl(vcpu, "unexpected exit reason 0x%llx\n", exit_reason);
+
+ vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+ vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_UNEXPECTED_EXIT_REASON;
+ vcpu->run->internal.ndata = 2;
+ vcpu->run->internal.data[0] = exit_reason;
+ vcpu->run->internal.data[1] = vcpu->arch.last_vmentry_cpu;
+}
+EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_prepare_unexpected_reason_exit);
+
static int handle_emulation_failure(struct kvm_vcpu *vcpu, int emulation_type)
{
struct kvm *kvm = vcpu->kvm;
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v2 0/2] KVM: VMX: Handle SEAMCALL or TDCALL VM-Exits
2025-10-16 18:21 [PATCH v2 0/2] KVM: VMX: Handle SEAMCALL or TDCALL VM-Exits Sean Christopherson
2025-10-16 18:21 ` [PATCH v2 1/2] KVM: VMX: Inject #UD if guest tries to execute SEAMCALL or TDCALL Sean Christopherson
2025-10-16 18:21 ` [PATCH v2 2/2] KVM: TDX: WARN if a SEAMCALL VM-Exit makes its way out to KVM Sean Christopherson
@ 2025-11-04 17:45 ` Sean Christopherson
2 siblings, 0 replies; 18+ messages in thread
From: Sean Christopherson @ 2025-11-04 17:45 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini
Cc: kvm, linux-kernel, Kai Huang, Xiaoyao Li, Rick Edgecombe,
Dan Williams, Binbin Wu
On Thu, 16 Oct 2025 11:21:46 -0700, Sean Christopherson wrote:
> Add VM-Exit handlers for SEAMCALL and TDCALL as the instructions are gated
> only by VMXON, and so a buggy/misbehaving guest will likely be terminated
> (because KVM bails with KVM_INTERNAL_ERROR_UNEXPECTED_EXIT_REASON) if the
> guest executes SEAMCALL or TDCALL.
>
> v2:
> - Apply the behavior only to VMX. KVM can't inject #UDs for TDX, and the
> TDX-Module is supposed to handle SEAMCALL. [Chao]
> - Fix nested exit handling (inverted return). [Xiaoyao]
> - WARN if the TDX-Module punts a SEAMCALL exit to KVM. [Xiaoyao]
> - Fix typos. [Binbin]
>
> [...]
Applied patch 1 to kvm-x86 fixes.
[1/2] KVM: VMX: Inject #UD if guest tries to execute SEAMCALL or TDCALL
https://github.com/kvm-x86/linux/commit/9d7dfb95da2c
--
https://github.com/kvm-x86/linux/tree/next
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2025-11-04 17:46 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-16 18:21 [PATCH v2 0/2] KVM: VMX: Handle SEAMCALL or TDCALL VM-Exits Sean Christopherson
2025-10-16 18:21 ` [PATCH v2 1/2] KVM: VMX: Inject #UD if guest tries to execute SEAMCALL or TDCALL Sean Christopherson
2025-10-17 2:53 ` Xiaoyao Li
2025-10-17 5:27 ` Binbin Wu
2025-10-17 10:53 ` Huang, Kai
2025-10-17 13:00 ` Sean Christopherson
2025-10-17 20:34 ` Huang, Kai
2025-10-17 20:34 ` Huang, Kai
2025-10-16 18:21 ` [PATCH v2 2/2] KVM: TDX: WARN if a SEAMCALL VM-Exit makes its way out to KVM Sean Christopherson
2025-10-17 2:56 ` Xiaoyao Li
2025-10-17 5:29 ` Binbin Wu
2025-10-17 10:40 ` Huang, Kai
2025-10-17 17:25 ` Sean Christopherson
2025-10-17 20:58 ` Huang, Kai
2025-10-17 21:11 ` Huang, Kai
2025-10-20 6:10 ` Xiaoyao Li
2025-10-20 15:03 ` Sean Christopherson
2025-11-04 17:45 ` [PATCH v2 0/2] KVM: VMX: Handle SEAMCALL or TDCALL VM-Exits Sean Christopherson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).