On Mon, 2024-02-26 at 00:25 -0800, isaku.yamahata@xxxxxxxxx wrote: > + > +static inline u64 tdh_mem_sept_add(hpa_t tdr, gpa_t gpa, int level, > hpa_t page, > + struct tdx_module_args *out) > +{ > + struct tdx_module_args in = { > + .rcx = gpa | level, > + .rdx = tdr, > + .r8 = page, > + }; > + > + clflush_cache_range(__va(page), PAGE_SIZE); > + return tdx_seamcall(TDH_MEM_SEPT_ADD, &in, out); > +} The caller of this later in the series looks like this: err = tdh_mem_sept_add(kvm_tdx, gpa, tdx_level, hpa, &out); if (unlikely(err == TDX_ERROR_SEPT_BUSY)) return -EAGAIN; if (unlikely(err == (TDX_EPT_ENTRY_STATE_INCORRECT | TDX_OPERAND_ID_RCX))) { union tdx_sept_entry entry = { .raw = out.rcx, }; union tdx_sept_level_state level_state = { .raw = out.rdx, }; /* someone updated the entry with same value. */ if (level_state.level == tdx_level && level_state.state == TDX_SEPT_PRESENT && !entry.leaf && entry.pfn == (hpa >> PAGE_SHIFT)) return -EAGAIN; } The helper abstracts setting the arguments into the proper registers fields passed in, but doesn't abstract pulling the result out from the register fields. Then the caller has to manually extract them in this verbose way. Why not have the helper do both?