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 * __tdcall() - Used by TDX guests to request services from the TDX 44 * module (does not include VMM services) using TDCALL instruction. 45 * 46 * __tdcall() function ABI: 47 * 48 * @fn (RDI) - TDCALL Leaf ID, moved to RAX 49 * @args (RSI) - struct tdx_module_args for input 50 * 51 * Return status of TDCALL via RAX. 52 */ 53SYM_FUNC_START(__tdcall) 54 TDX_MODULE_CALL host=0 55SYM_FUNC_END(__tdcall) 56 57/* 58 * __tdcall_ret() - Used by TDX guests to request services from the TDX 59 * module (does not include VMM services) using TDCALL instruction, with 60 * saving output registers to the 'struct tdx_module_args' used as input. 61 * 62 * __tdcall_ret() function ABI: 63 * 64 * @fn (RDI) - TDCALL Leaf ID, moved to RAX 65 * @args (RSI) - struct tdx_module_args for input and output 66 * 67 * Return status of TDCALL via RAX. 68 */ 69SYM_FUNC_START(__tdcall_ret) 70 TDX_MODULE_CALL host=0 ret=1 71SYM_FUNC_END(__tdcall_ret) 72 73/* 74 * TDX_HYPERCALL - Make hypercalls to a TDX VMM using TDVMCALL leaf of TDCALL 75 * instruction 76 * 77 * Transforms values in function call argument struct tdx_hypercall_args @args 78 * into the TDCALL register ABI. After TDCALL operation, VMM output is saved 79 * back in @args, if \ret is 1. 80 * 81 *------------------------------------------------------------------------- 82 * TD VMCALL ABI: 83 *------------------------------------------------------------------------- 84 * 85 * Input Registers: 86 * 87 * RAX - TDCALL instruction leaf number (0 - TDG.VP.VMCALL) 88 * RCX - BITMAP which controls which part of TD Guest GPR 89 * is passed as-is to the VMM and back. 90 * R10 - Set 0 to indicate TDCALL follows standard TDX ABI 91 * specification. Non zero value indicates vendor 92 * specific ABI. 93 * R11 - VMCALL sub function number 94 * RBX, RDX, RDI, RSI - Used to pass VMCALL sub function specific arguments. 95 * R8-R9, R12-R15 - Same as above. 96 * 97 * Output Registers: 98 * 99 * RAX - TDCALL instruction status (Not related to hypercall 100 * output). 101 * RBX, RDX, RDI, RSI - Hypercall sub function specific output values. 102 * R8-R15 - Same as above. 103 * 104 */ 105.macro TDX_HYPERCALL ret:req 106 FRAME_BEGIN 107 108 /* Save callee-saved GPRs as mandated by the x86_64 ABI */ 109 push %r15 110 push %r14 111 push %r13 112 push %r12 113 push %rbx 114 115 /* Free RDI to be used as TDVMCALL arguments */ 116 movq %rdi, %rax 117 118 /* Copy hypercall registers from arg struct: */ 119 movq TDX_HYPERCALL_r8(%rax), %r8 120 movq TDX_HYPERCALL_r9(%rax), %r9 121 movq TDX_HYPERCALL_r10(%rax), %r10 122 movq TDX_HYPERCALL_r11(%rax), %r11 123 movq TDX_HYPERCALL_r12(%rax), %r12 124 movq TDX_HYPERCALL_r13(%rax), %r13 125 movq TDX_HYPERCALL_r14(%rax), %r14 126 movq TDX_HYPERCALL_r15(%rax), %r15 127 movq TDX_HYPERCALL_rdi(%rax), %rdi 128 movq TDX_HYPERCALL_rsi(%rax), %rsi 129 movq TDX_HYPERCALL_rbx(%rax), %rbx 130 movq TDX_HYPERCALL_rdx(%rax), %rdx 131 132 push %rax 133 134 /* Mangle function call ABI into TDCALL ABI: */ 135 /* Set TDCALL leaf ID (TDVMCALL (0)) in RAX */ 136 xor %eax, %eax 137 138 movl $TDVMCALL_EXPOSE_REGS_MASK, %ecx 139 140 tdcall 141 142 /* 143 * RAX!=0 indicates a failure of the TDVMCALL mechanism itself and that 144 * something has gone horribly wrong with the TDX module. 145 * 146 * The return status of the hypercall operation is in a separate 147 * register (in R10). Hypercall errors are a part of normal operation 148 * and are handled by callers. 149 */ 150 testq %rax, %rax 151 jne .Lpanic\@ 152 153 pop %rax 154 155 .if \ret 156 movq %r8, TDX_HYPERCALL_r8(%rax) 157 movq %r9, TDX_HYPERCALL_r9(%rax) 158 movq %r10, TDX_HYPERCALL_r10(%rax) 159 movq %r11, TDX_HYPERCALL_r11(%rax) 160 movq %r12, TDX_HYPERCALL_r12(%rax) 161 movq %r13, TDX_HYPERCALL_r13(%rax) 162 movq %r14, TDX_HYPERCALL_r14(%rax) 163 movq %r15, TDX_HYPERCALL_r15(%rax) 164 movq %rdi, TDX_HYPERCALL_rdi(%rax) 165 movq %rsi, TDX_HYPERCALL_rsi(%rax) 166 movq %rbx, TDX_HYPERCALL_rbx(%rax) 167 movq %rdx, TDX_HYPERCALL_rdx(%rax) 168 .endif 169 170 /* TDVMCALL leaf return code is in R10 */ 171 movq %r10, %rax 172 173 /* 174 * Zero out registers exposed to the VMM to avoid speculative execution 175 * with VMM-controlled values. This needs to include all registers 176 * present in TDVMCALL_EXPOSE_REGS_MASK, except RBX, and R12-R15 which 177 * will be restored. 178 */ 179 xor %r8d, %r8d 180 xor %r9d, %r9d 181 xor %r10d, %r10d 182 xor %r11d, %r11d 183 xor %rdi, %rdi 184 xor %rsi, %rsi 185 xor %rdx, %rdx 186 187 /* Restore callee-saved GPRs as mandated by the x86_64 ABI */ 188 pop %rbx 189 pop %r12 190 pop %r13 191 pop %r14 192 pop %r15 193 194 FRAME_END 195 196 RET 197.Lpanic\@: 198 call __tdx_hypercall_failed 199 /* __tdx_hypercall_failed never returns */ 200 REACHABLE 201 jmp .Lpanic\@ 202.endm 203 204/* 205 * 206 * __tdx_hypercall() function ABI: 207 * 208 * @args (RDI) - struct tdx_hypercall_args for input 209 * 210 * On successful completion, return the hypercall error code. 211 */ 212SYM_FUNC_START(__tdx_hypercall) 213 TDX_HYPERCALL ret=0 214SYM_FUNC_END(__tdx_hypercall) 215 216/* 217 * 218 * __tdx_hypercall_ret() function ABI: 219 * 220 * @args (RDI) - struct tdx_hypercall_args for input and output 221 * 222 * On successful completion, return the hypercall error code. 223 */ 224SYM_FUNC_START(__tdx_hypercall_ret) 225 TDX_HYPERCALL ret=1 226SYM_FUNC_END(__tdx_hypercall_ret) 227