TDCALL calls are centralized into a few megawrappers that take the
struct tdx_module_args as input. Most of the call sites only use a few
arguments, but they have to zero out unused fields in the structure to
avoid data leaks to the VMM. This leads to the compiler generating
inefficient code: dozens of instructions per call site to clear unused
fields of the structure.

This issue can be avoided by using more targeted wrappers.
tdvmcall_trampoline() provides a common base for them.

The function will be used from inline assembly to handle most TDVMCALL
cases.

Signed-off-by: Kirill A. Shutemov <kirill.shute...@linux.intel.com>
---
 arch/x86/coco/tdx/tdcall.S | 49 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/arch/x86/coco/tdx/tdcall.S b/arch/x86/coco/tdx/tdcall.S
index 52d9786da308..12185fbd33ba 100644
--- a/arch/x86/coco/tdx/tdcall.S
+++ b/arch/x86/coco/tdx/tdcall.S
@@ -61,3 +61,52 @@ SYM_FUNC_END(__tdcall_ret)
 SYM_FUNC_START(__tdcall_saved_ret)
        TDX_MODULE_CALL host=0 ret=1 saved=1
 SYM_FUNC_END(__tdcall_saved_ret)
+
+/*
+ * tdvmcall_trampoline() - Wrapper for TDG.VP.VMCALL. Covers common cases: up
+ * to five input and out arguments.
+ *
+ * tdvmcall_trampoline() function ABI is not SYSV ABI compliant. Caller has to
+ * deal with it.
+ *
+ * Input:
+ * RAX - Type of call, TDX_HYPERCALL_STANDARD for calls defined in GHCI spec
+ * RBX - 1st argument (R11), leaf ID if RAX is TDX_HYPERCALL_STANDARD
+ * RDI - 2nd argument (R12)
+ * RSI - 3rd argument (R13)
+ * RDX - 4th argument (R14)
+ * RCX - 5th argument (R15)
+ *
+ * Output:
+ * R10 - TDVMCALL error code
+ * R11 - Output 1
+ * R12 - Output 2
+ * R13 - Output 3
+ * R14 - Output 4
+ * R15 - Output 5
+ */
+.pushsection .noinstr.text, "ax"
+SYM_FUNC_START(tdvmcall_trampoline)
+       movq    %rax, %r10
+       movq    %rbx, %r11
+       movq    %rdi, %r12
+       movq    %rsi, %r13
+       movq    %rdx, %r14
+       movq    %rcx, %r15
+
+       movq    $TDG_VP_VMCALL, %rax
+
+       /* RCX is bitmap of registers exposed to VMM on TDG.VM.VMCALL */
+       movq    $(TDX_R10 | TDX_R11 | TDX_R12 | TDX_R13 | TDX_R14 | TDX_R15), 
%rcx
+
+       tdcall
+
+       /* TDG.VP.VMCALL never fails on correct use. Panic if it fails. */
+       testq   %rax, %rax
+       jnz     .Lpanic
+
+       RET
+.Lpanic:
+       ud2
+SYM_FUNC_END(tdvmcall_trampoline)
+.popsection
-- 
2.43.0


Reply via email to