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_RDX BIT(2) 17#define TDX_RBX BIT(3) 18#define TDX_RSI BIT(6) 19#define TDX_RDI BIT(7) 20#define TDX_R8 BIT(8) 21#define TDX_R9 BIT(9) 22#define TDX_R10 BIT(10) 23#define TDX_R11 BIT(11) 24#define TDX_R12 BIT(12) 25#define TDX_R13 BIT(13) 26#define TDX_R14 BIT(14) 27#define TDX_R15 BIT(15) 28 29/* 30 * These registers are clobbered to hold arguments for each 31 * TDVMCALL. They are safe to expose to the VMM. 32 * Each bit in this mask represents a register ID. Bit field 33 * details can be found in TDX GHCI specification, section 34 * titled "TDCALL [TDG.VP.VMCALL] leaf". 35 */ 36#define TDVMCALL_EXPOSE_REGS_MASK \ 37 ( TDX_RDX | TDX_RBX | TDX_RSI | TDX_RDI | TDX_R8 | TDX_R9 | \ 38 TDX_R10 | TDX_R11 | TDX_R12 | TDX_R13 | TDX_R14 | TDX_R15 ) 39 40.section .noinstr.text, "ax" 41 42/* 43 * __tdx_module_call() - Used by TDX guests to request services from 44 * the TDX module (does not include VMM services) using TDCALL instruction. 45 * 46 * Transforms function call register arguments into the TDCALL register ABI. 47 * After TDCALL operation, TDX module output is saved in @out (if it is 48 * provided by the user). 49 * 50 *------------------------------------------------------------------------- 51 * TDCALL ABI: 52 *------------------------------------------------------------------------- 53 * Input Registers: 54 * 55 * RAX - TDCALL Leaf number. 56 * RCX,RDX,R8-R9 - TDCALL Leaf specific input registers. 57 * 58 * Output Registers: 59 * 60 * RAX - TDCALL instruction error code. 61 * RCX,RDX,R8-R11 - TDCALL Leaf specific output registers. 62 * 63 *------------------------------------------------------------------------- 64 * 65 * __tdx_module_call() function ABI: 66 * 67 * @fn (RDI) - TDCALL Leaf ID, moved to RAX 68 * @rcx (RSI) - Input parameter 1, moved to RCX 69 * @rdx (RDX) - Input parameter 2, moved to RDX 70 * @r8 (RCX) - Input parameter 3, moved to R8 71 * @r9 (R8) - Input parameter 4, moved to R9 72 * 73 * @out (R9) - struct tdx_module_output pointer 74 * stored temporarily in R12 (not 75 * shared with the TDX module). It 76 * can be NULL. 77 * 78 * Return status of TDCALL via RAX. 79 */ 80SYM_FUNC_START(__tdx_module_call) 81 FRAME_BEGIN 82 TDX_MODULE_CALL host=0 83 FRAME_END 84 RET 85SYM_FUNC_END(__tdx_module_call) 86 87/* 88 * TDX_HYPERCALL - Make hypercalls to a TDX VMM using TDVMCALL leaf of TDCALL 89 * instruction 90 * 91 * Transforms values in function call argument struct tdx_hypercall_args @args 92 * into the TDCALL register ABI. After TDCALL operation, VMM output is saved 93 * back in @args, if \ret is 1. 94 * 95 *------------------------------------------------------------------------- 96 * TD VMCALL ABI: 97 *------------------------------------------------------------------------- 98 * 99 * Input Registers: 100 * 101 * RAX - TDCALL instruction leaf number (0 - TDG.VP.VMCALL) 102 * RCX - BITMAP which controls which part of TD Guest GPR 103 * is passed as-is to the VMM and back. 104 * R10 - Set 0 to indicate TDCALL follows standard TDX ABI 105 * specification. Non zero value indicates vendor 106 * specific ABI. 107 * R11 - VMCALL sub function number 108 * RBX, RDX, RDI, RSI - Used to pass VMCALL sub function specific arguments. 109 * R8-R9, R12-R15 - Same as above. 110 * 111 * Output Registers: 112 * 113 * RAX - TDCALL instruction status (Not related to hypercall 114 * output). 115 * RBX, RDX, RDI, RSI - Hypercall sub function specific output values. 116 * R8-R15 - Same as above. 117 * 118 */ 119.macro TDX_HYPERCALL ret:req 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 %rbx 128 129 /* Free RDI to be used as TDVMCALL arguments */ 130 movq %rdi, %rax 131 132 /* Copy hypercall registers from arg struct: */ 133 movq TDX_HYPERCALL_r8(%rax), %r8 134 movq TDX_HYPERCALL_r9(%rax), %r9 135 movq TDX_HYPERCALL_r10(%rax), %r10 136 movq TDX_HYPERCALL_r11(%rax), %r11 137 movq TDX_HYPERCALL_r12(%rax), %r12 138 movq TDX_HYPERCALL_r13(%rax), %r13 139 movq TDX_HYPERCALL_r14(%rax), %r14 140 movq TDX_HYPERCALL_r15(%rax), %r15 141 movq TDX_HYPERCALL_rdi(%rax), %rdi 142 movq TDX_HYPERCALL_rsi(%rax), %rsi 143 movq TDX_HYPERCALL_rbx(%rax), %rbx 144 movq TDX_HYPERCALL_rdx(%rax), %rdx 145 146 push %rax 147 148 /* Mangle function call ABI into TDCALL ABI: */ 149 /* Set TDCALL leaf ID (TDVMCALL (0)) in RAX */ 150 xor %eax, %eax 151 152 movl $TDVMCALL_EXPOSE_REGS_MASK, %ecx 153 154 tdcall 155 156 /* 157 * RAX!=0 indicates a failure of the TDVMCALL mechanism itself and that 158 * something has gone horribly wrong with the TDX module. 159 * 160 * The return status of the hypercall operation is in a separate 161 * register (in R10). Hypercall errors are a part of normal operation 162 * and are handled by callers. 163 */ 164 testq %rax, %rax 165 jne .Lpanic\@ 166 167 pop %rax 168 169 .if \ret 170 movq %r8, TDX_HYPERCALL_r8(%rax) 171 movq %r9, TDX_HYPERCALL_r9(%rax) 172 movq %r10, TDX_HYPERCALL_r10(%rax) 173 movq %r11, TDX_HYPERCALL_r11(%rax) 174 movq %r12, TDX_HYPERCALL_r12(%rax) 175 movq %r13, TDX_HYPERCALL_r13(%rax) 176 movq %r14, TDX_HYPERCALL_r14(%rax) 177 movq %r15, TDX_HYPERCALL_r15(%rax) 178 movq %rdi, TDX_HYPERCALL_rdi(%rax) 179 movq %rsi, TDX_HYPERCALL_rsi(%rax) 180 movq %rbx, TDX_HYPERCALL_rbx(%rax) 181 movq %rdx, TDX_HYPERCALL_rdx(%rax) 182 .endif 183 184 /* TDVMCALL leaf return code is in R10 */ 185 movq %r10, %rax 186 187 /* 188 * Zero out registers exposed to the VMM to avoid speculative execution 189 * with VMM-controlled values. This needs to include all registers 190 * present in TDVMCALL_EXPOSE_REGS_MASK, except RBX, and R12-R15 which 191 * will be restored. 192 */ 193 xor %r8d, %r8d 194 xor %r9d, %r9d 195 xor %r10d, %r10d 196 xor %r11d, %r11d 197 xor %rdi, %rdi 198 xor %rsi, %rsi 199 xor %rdx, %rdx 200 201 /* Restore callee-saved GPRs as mandated by the x86_64 ABI */ 202 pop %rbx 203 pop %r12 204 pop %r13 205 pop %r14 206 pop %r15 207 208 FRAME_END 209 210 RET 211.Lpanic\@: 212 call __tdx_hypercall_failed 213 /* __tdx_hypercall_failed never returns */ 214 REACHABLE 215 jmp .Lpanic\@ 216.endm 217 218/* 219 * 220 * __tdx_hypercall() function ABI: 221 * 222 * @args (RDI) - struct tdx_hypercall_args for input 223 * 224 * On successful completion, return the hypercall error code. 225 */ 226SYM_FUNC_START(__tdx_hypercall) 227 TDX_HYPERCALL ret=0 228SYM_FUNC_END(__tdx_hypercall) 229 230/* 231 * 232 * __tdx_hypercall_ret() function ABI: 233 * 234 * @args (RDI) - struct tdx_hypercall_args for input and output 235 * 236 * On successful completion, return the hypercall error code. 237 */ 238SYM_FUNC_START(__tdx_hypercall_ret) 239 TDX_HYPERCALL ret=1 240SYM_FUNC_END(__tdx_hypercall_ret) 241