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