/* SPDX-License-Identifier: GPL-2.0 */ #include #include /* * TDCALL and SEAMCALL are supported in Binutils >= 2.36. */ #define tdcall .byte 0x66,0x0f,0x01,0xcc #define seamcall .byte 0x66,0x0f,0x01,0xcf /* * TDX_MODULE_CALL - common helper macro for both * TDCALL and SEAMCALL instructions. * * TDCALL - used by TDX guests to make requests to the * TDX module and hypercalls to the VMM. * SEAMCALL - used by TDX hosts to make requests to the * TDX module. */ .macro TDX_MODULE_CALL host:req /* * R12 will be used as temporary storage for struct tdx_module_output * pointer. Since R12-R15 registers are not used by TDCALL/SEAMCALL * services supported by this function, it can be reused. */ /* Callee saved, so preserve it */ push %r12 /* * Push output pointer to stack. * After the operation, it will be fetched into R12 register. */ push %r9 /* Mangle function call ABI into TDCALL/SEAMCALL ABI: */ /* Move Leaf ID to RAX */ mov %rdi, %rax /* Move input 4 to R9 */ mov %r8, %r9 /* Move input 3 to R8 */ mov %rcx, %r8 /* Move input 1 to RCX */ mov %rsi, %rcx /* Leave input param 2 in RDX */ .if \host seamcall /* * SEAMCALL instruction is essentially a VMExit from VMX root * mode to SEAM VMX root mode. VMfailInvalid (CF=1) indicates * that the targeted SEAM firmware is not loaded or disabled, * or P-SEAMLDR is busy with another SEAMCALL. %rax is not * changed in this case. * * Set %rax to TDX_SEAMCALL_VMFAILINVALID for VMfailInvalid. * This value will never be used as actual SEAMCALL error code as * it is from the Reserved status code class. */ jnc .Lno_vmfailinvalid mov $TDX_SEAMCALL_VMFAILINVALID, %rax .Lno_vmfailinvalid: .else tdcall .endif /* * Fetch output pointer from stack to R12 (It is used * as temporary storage) */ pop %r12 /* * Since this macro can be invoked with NULL as an output pointer, * check if caller provided an output struct before storing output * registers. * * Update output registers, even if the call failed (RAX != 0). * Other registers may contain details of the failure. */ test %r12, %r12 jz .Lno_output_struct /* Copy result registers to output struct: */ movq %rcx, TDX_MODULE_rcx(%r12) movq %rdx, TDX_MODULE_rdx(%r12) movq %r8, TDX_MODULE_r8(%r12) movq %r9, TDX_MODULE_r9(%r12) movq %r10, TDX_MODULE_r10(%r12) movq %r11, TDX_MODULE_r11(%r12) .Lno_output_struct: /* Restore the state of R12 register */ pop %r12 .endm