|
| 1 | +/* SPDX-License-Identifier: GPL-2.0 */ |
| 2 | +#include <asm/asm-offsets.h> |
| 3 | +#include <asm/tdx.h> |
| 4 | + |
| 5 | +/* |
| 6 | + * TDCALL and SEAMCALL are supported in Binutils >= 2.36. |
| 7 | + */ |
| 8 | +#define tdcall .byte 0x66,0x0f,0x01,0xcc |
| 9 | +#define seamcall .byte 0x66,0x0f,0x01,0xcf |
| 10 | + |
| 11 | +/* |
| 12 | + * TDX_MODULE_CALL - common helper macro for both |
| 13 | + * TDCALL and SEAMCALL instructions. |
| 14 | + * |
| 15 | + * TDCALL - used by TDX guests to make requests to the |
| 16 | + * TDX module and hypercalls to the VMM. |
| 17 | + * SEAMCALL - used by TDX hosts to make requests to the |
| 18 | + * TDX module. |
| 19 | + */ |
| 20 | +.macro TDX_MODULE_CALL host:req |
| 21 | + /* |
| 22 | + * R12 will be used as temporary storage for struct tdx_module_output |
| 23 | + * pointer. Since R12-R15 registers are not used by TDCALL/SEAMCALL |
| 24 | + * services supported by this function, it can be reused. |
| 25 | + */ |
| 26 | + |
| 27 | + /* Callee saved, so preserve it */ |
| 28 | + push %r12 |
| 29 | + |
| 30 | + /* |
| 31 | + * Push output pointer to stack. |
| 32 | + * After the operation, it will be fetched into R12 register. |
| 33 | + */ |
| 34 | + push %r9 |
| 35 | + |
| 36 | + /* Mangle function call ABI into TDCALL/SEAMCALL ABI: */ |
| 37 | + /* Move Leaf ID to RAX */ |
| 38 | + mov %rdi, %rax |
| 39 | + /* Move input 4 to R9 */ |
| 40 | + mov %r8, %r9 |
| 41 | + /* Move input 3 to R8 */ |
| 42 | + mov %rcx, %r8 |
| 43 | + /* Move input 1 to RCX */ |
| 44 | + mov %rsi, %rcx |
| 45 | + /* Leave input param 2 in RDX */ |
| 46 | + |
| 47 | + .if \host |
| 48 | + seamcall |
| 49 | + /* |
| 50 | + * SEAMCALL instruction is essentially a VMExit from VMX root |
| 51 | + * mode to SEAM VMX root mode. VMfailInvalid (CF=1) indicates |
| 52 | + * that the targeted SEAM firmware is not loaded or disabled, |
| 53 | + * or P-SEAMLDR is busy with another SEAMCALL. %rax is not |
| 54 | + * changed in this case. |
| 55 | + * |
| 56 | + * Set %rax to TDX_SEAMCALL_VMFAILINVALID for VMfailInvalid. |
| 57 | + * This value will never be used as actual SEAMCALL error code as |
| 58 | + * it is from the Reserved status code class. |
| 59 | + */ |
| 60 | + jnc .Lno_vmfailinvalid |
| 61 | + mov $TDX_SEAMCALL_VMFAILINVALID, %rax |
| 62 | +.Lno_vmfailinvalid: |
| 63 | + |
| 64 | + .else |
| 65 | + tdcall |
| 66 | + .endif |
| 67 | + |
| 68 | + /* |
| 69 | + * Fetch output pointer from stack to R12 (It is used |
| 70 | + * as temporary storage) |
| 71 | + */ |
| 72 | + pop %r12 |
| 73 | + |
| 74 | + /* |
| 75 | + * Since this macro can be invoked with NULL as an output pointer, |
| 76 | + * check if caller provided an output struct before storing output |
| 77 | + * registers. |
| 78 | + * |
| 79 | + * Update output registers, even if the call failed (RAX != 0). |
| 80 | + * Other registers may contain details of the failure. |
| 81 | + */ |
| 82 | + test %r12, %r12 |
| 83 | + jz .Lno_output_struct |
| 84 | + |
| 85 | + /* Copy result registers to output struct: */ |
| 86 | + movq %rcx, TDX_MODULE_rcx(%r12) |
| 87 | + movq %rdx, TDX_MODULE_rdx(%r12) |
| 88 | + movq %r8, TDX_MODULE_r8(%r12) |
| 89 | + movq %r9, TDX_MODULE_r9(%r12) |
| 90 | + movq %r10, TDX_MODULE_r10(%r12) |
| 91 | + movq %r11, TDX_MODULE_r11(%r12) |
| 92 | + |
| 93 | +.Lno_output_struct: |
| 94 | + /* Restore the state of R12 register */ |
| 95 | + pop %r12 |
| 96 | +.endm |
0 commit comments