1/* SPDX-License-Identifier: GPL-2.0 */ 2#include <asm/asm-offsets.h> 3#include <asm/asm.h> 4#include <asm/frame.h> 5#include <asm/unwind_hints.h> 6 7#include <linux/linkage.h> 8#include <linux/bits.h> 9#include <linux/errno.h> 10 11#include "../../virt/vmx/tdx/tdxcall.S" 12 13/* 14 * Bitmasks of exposed registers (with VMM). 15 */ 16#define TDX_R10 BIT(10) 17#define TDX_R11 BIT(11) 18#define TDX_R12 BIT(12) 19#define TDX_R13 BIT(13) 20#define TDX_R14 BIT(14) 21#define TDX_R15 BIT(15) 22 23/* 24 * These registers are clobbered to hold arguments for each 25 * TDVMCALL. They are safe to expose to the VMM. 26 * Each bit in this mask represents a register ID. Bit field 27 * details can be found in TDX GHCI specification, section 28 * titled "TDCALL [TDG.VP.VMCALL] leaf". 29 */ 30#define TDVMCALL_EXPOSE_REGS_MASK ( TDX_R10 | TDX_R11 | \ 31 TDX_R12 | TDX_R13 | \ 32 TDX_R14 | TDX_R15 ) 33 34/* 35 * __tdx_module_call() - Used by TDX guests to request services from 36 * the TDX module (does not include VMM services) using TDCALL instruction. 37 * 38 * Transforms function call register arguments into the TDCALL register ABI. 39 * After TDCALL operation, TDX module output is saved in @out (if it is 40 * provided by the user). 41 * 42 *------------------------------------------------------------------------- 43 * TDCALL ABI: 44 *------------------------------------------------------------------------- 45 * Input Registers: 46 * 47 * RAX - TDCALL Leaf number. 48 * RCX,RDX,R8-R9 - TDCALL Leaf specific input registers. 49 * 50 * Output Registers: 51 * 52 * RAX - TDCALL instruction error code. 53 * RCX,RDX,R8-R11 - TDCALL Leaf specific output registers. 54 * 55 *------------------------------------------------------------------------- 56 * 57 * __tdx_module_call() function ABI: 58 * 59 * @fn (RDI) - TDCALL Leaf ID, moved to RAX 60 * @rcx (RSI) - Input parameter 1, moved to RCX 61 * @rdx (RDX) - Input parameter 2, moved to RDX 62 * @r8 (RCX) - Input parameter 3, moved to R8 63 * @r9 (R8) - Input parameter 4, moved to R9 64 * 65 * @out (R9) - struct tdx_module_output pointer 66 * stored temporarily in R12 (not 67 * shared with the TDX module). It 68 * can be NULL. 69 * 70 * Return status of TDCALL via RAX. 71 */ 72SYM_FUNC_START(__tdx_module_call) 73 FRAME_BEGIN 74 TDX_MODULE_CALL host=0 75 FRAME_END 76 RET 77SYM_FUNC_END(__tdx_module_call) 78 79/* 80 * __tdx_hypercall() - Make hypercalls to a TDX VMM using TDVMCALL leaf 81 * of TDCALL instruction 82 * 83 * Transforms values in function call argument struct tdx_hypercall_args @args 84 * into the TDCALL register ABI. After TDCALL operation, VMM output is saved 85 * back in @args. 86 * 87 *------------------------------------------------------------------------- 88 * TD VMCALL ABI: 89 *------------------------------------------------------------------------- 90 * 91 * Input Registers: 92 * 93 * RAX - TDCALL instruction leaf number (0 - TDG.VP.VMCALL) 94 * RCX - BITMAP which controls which part of TD Guest GPR 95 * is passed as-is to the VMM and back. 96 * R10 - Set 0 to indicate TDCALL follows standard TDX ABI 97 * specification. Non zero value indicates vendor 98 * specific ABI. 99 * R11 - VMCALL sub function number 100 * RBX, RBP, RDI, RSI - Used to pass VMCALL sub function specific arguments. 101 * R8-R9, R12-R15 - Same as above. 102 * 103 * Output Registers: 104 * 105 * RAX - TDCALL instruction status (Not related to hypercall 106 * output). 107 * R10 - Hypercall output error code. 108 * R11-R15 - Hypercall sub function specific output values. 109 * 110 *------------------------------------------------------------------------- 111 * 112 * __tdx_hypercall() function ABI: 113 * 114 * @args (RDI) - struct tdx_hypercall_args for input and output 115 * @flags (RSI) - TDX_HCALL_* flags 116 * 117 * On successful completion, return the hypercall error code. 118 */ 119SYM_FUNC_START(__tdx_hypercall) 120 FRAME_BEGIN 121 122 /* Save callee-saved GPRs as mandated by the x86_64 ABI */ 123 push %r15 124 push %r14 125 push %r13 126 push %r12 127 push %rbp 128 129 /* Free RDI and RSI to be used as TDVMCALL arguments */ 130 movq %rdi, %rax 131 movq %rsi, %rbp 132 133 /* Copy hypercall registers from arg struct: */ 134 movq TDX_HYPERCALL_r10(%rax), %r10 135 movq TDX_HYPERCALL_r11(%rax), %r11 136 movq TDX_HYPERCALL_r12(%rax), %r12 137 movq TDX_HYPERCALL_r13(%rax), %r13 138 movq TDX_HYPERCALL_r14(%rax), %r14 139 movq TDX_HYPERCALL_r15(%rax), %r15 140 141 push %rax 142 143 /* Mangle function call ABI into TDCALL ABI: */ 144 /* Set TDCALL leaf ID (TDVMCALL (0)) in RAX */ 145 xor %eax, %eax 146 147 movl $TDVMCALL_EXPOSE_REGS_MASK, %ecx 148 149 /* 150 * For the idle loop STI needs to be called directly before the TDCALL 151 * that enters idle (EXIT_REASON_HLT case). STI instruction enables 152 * interrupts only one instruction later. If there is a window between 153 * STI and the instruction that emulates the HALT state, there is a 154 * chance for interrupts to happen in this window, which can delay the 155 * HLT operation indefinitely. Since this is the not the desired 156 * result, conditionally call STI before TDCALL. 157 */ 158 testq $TDX_HCALL_ISSUE_STI, %rbp 159 jz .Lskip_sti 160 sti 161.Lskip_sti: 162 tdcall 163 164 /* 165 * RAX!=0 indicates a failure of the TDVMCALL mechanism itself and that 166 * something has gone horribly wrong with the TDX module. 167 * 168 * The return status of the hypercall operation is in a separate 169 * register (in R10). Hypercall errors are a part of normal operation 170 * and are handled by callers. 171 */ 172 testq %rax, %rax 173 jne .Lpanic 174 175 pop %rax 176 177 /* Copy hypercall result registers to arg struct if needed */ 178 testq $TDX_HCALL_HAS_OUTPUT, %rbp 179 jz .Lout 180 181 movq %r10, TDX_HYPERCALL_r10(%rax) 182 movq %r11, TDX_HYPERCALL_r11(%rax) 183 movq %r12, TDX_HYPERCALL_r12(%rax) 184 movq %r13, TDX_HYPERCALL_r13(%rax) 185 movq %r14, TDX_HYPERCALL_r14(%rax) 186 movq %r15, TDX_HYPERCALL_r15(%rax) 187.Lout: 188 /* TDVMCALL leaf return code is in R10 */ 189 movq %r10, %rax 190 191 /* 192 * Zero out registers exposed to the VMM to avoid speculative execution 193 * with VMM-controlled values. This needs to include all registers 194 * present in TDVMCALL_EXPOSE_REGS_MASK (except R12-R15). R12-R15 195 * context will be restored. 196 */ 197 xor %r10d, %r10d 198 xor %r11d, %r11d 199 200 /* Restore callee-saved GPRs as mandated by the x86_64 ABI */ 201 pop %rbp 202 pop %r12 203 pop %r13 204 pop %r14 205 pop %r15 206 207 FRAME_END 208 209 RET 210.Lpanic: 211 call __tdx_hypercall_failed 212 /* __tdx_hypercall_failed never returns */ 213 REACHABLE 214 jmp .Lpanic 215SYM_FUNC_END(__tdx_hypercall) 216