[PATCH v2 20/31] x86/virt/tdx: Add a helper to loop on TDX_INTERRUPTED_RESUMABLE

Xu Yilun
2026-03-27T16:23:48Z

Add a helper to handle SEAMCALL return code TDX_INTERRUPTED_RESUMABLE.

SEAMCALL returns TDX_INTERRUPTED_RESUMABLE to avoid stalling host for
long time. After host has handled the interrupt, it calls the
interrupted SEAMCALL again and TDX Module continues to execute. TDX
Module made progress in this case and would eventually finish. An
infinite loop in host should be safe.

The helper is for SEAMCALL wrappers which output information by using
seamcall_ret() or seamcall_saved_ret(). The 2 functions overwrite input
arguments by outputs but much SEAMCALLs expect the same inputs to
resume.

The helper is not for special cases where the SEAMCALL expects modified
inputs to resume. The helper is also not for SEAMCALLs with no output,
do {...} while (r == TDX_INTERRUPTED_RESUMABLE) just works.

Signed-off-by: Xu Yilun <yilun.xu@linux.intel.com>
---
arch/x86/virt/vmx/tdx/tdx.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)

diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
index cd0948794b6c..294f36048c03 100644
--- a/arch/x86/virt/vmx/tdx/tdx.c
+++ b/arch/x86/virt/vmx/tdx/tdx.c
@@ -2084,6 +2084,29 @@ static inline u64 tdx_tdr_pa(struct tdx_td *td)
return page_to_phys(td->tdr_page);
}

+static u64 __maybe_unused __seamcall_ir_resched(sc_func_t sc_func, u64 fn,
+ struct tdx_module_args *args)
+{
+ struct tdx_module_args _args;
+ u64 r;
+
+ while (1) {
+ _args = *(args);
+ r = sc_retry(sc_func, fn, &_args);
+ if (r != TDX_INTERRUPTED_RESUMABLE)
+ break;
+
+ cond_resched();
+ }
+
+ *args = _args;
+
+ return r;
+}
+
+#define seamcall_ret_ir_resched(fn, args) \
+ __seamcall_ir_resched(__seamcall_ret, fn, args)
+
noinstr u64 tdh_vp_enter(struct tdx_vp *td, struct tdx_module_args *args)
{
args->rcx = td->tdvpr_pa;
--
2.25.1