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 --- 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 46cdb5aaaf68..7bc2c900a8a8 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -2003,6 +2003,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