![]() |
|
|||
0001 /* SPDX-License-Identifier: GPL-2.0 */ 0002 #include <asm/asm-offsets.h> 0003 #include <asm/asm.h> 0004 #include <asm/frame.h> 0005 #include <asm/unwind_hints.h> 0006 0007 #include <linux/linkage.h> 0008 #include <linux/bits.h> 0009 #include <linux/errno.h> 0010 0011 #include "../../virt/vmx/tdx/tdxcall.S" 0012 0013 /* 0014 * Bitmasks of exposed registers (with VMM). 0015 */ 0016 #define TDX_R10 BIT(10) 0017 #define TDX_R11 BIT(11) 0018 #define TDX_R12 BIT(12) 0019 #define TDX_R13 BIT(13) 0020 #define TDX_R14 BIT(14) 0021 #define TDX_R15 BIT(15) 0022 0023 /* 0024 * These registers are clobbered to hold arguments for each 0025 * TDVMCALL. They are safe to expose to the VMM. 0026 * Each bit in this mask represents a register ID. Bit field 0027 * details can be found in TDX GHCI specification, section 0028 * titled "TDCALL [TDG.VP.VMCALL] leaf". 0029 */ 0030 #define TDVMCALL_EXPOSE_REGS_MASK ( TDX_R10 | TDX_R11 | \ 0031 TDX_R12 | TDX_R13 | \ 0032 TDX_R14 | TDX_R15 ) 0033 0034 /* 0035 * __tdx_module_call() - Used by TDX guests to request services from 0036 * the TDX module (does not include VMM services) using TDCALL instruction. 0037 * 0038 * Transforms function call register arguments into the TDCALL register ABI. 0039 * After TDCALL operation, TDX module output is saved in @out (if it is 0040 * provided by the user). 0041 * 0042 *------------------------------------------------------------------------- 0043 * TDCALL ABI: 0044 *------------------------------------------------------------------------- 0045 * Input Registers: 0046 * 0047 * RAX - TDCALL Leaf number. 0048 * RCX,RDX,R8-R9 - TDCALL Leaf specific input registers. 0049 * 0050 * Output Registers: 0051 * 0052 * RAX - TDCALL instruction error code. 0053 * RCX,RDX,R8-R11 - TDCALL Leaf specific output registers. 0054 * 0055 *------------------------------------------------------------------------- 0056 * 0057 * __tdx_module_call() function ABI: 0058 * 0059 * @fn (RDI) - TDCALL Leaf ID, moved to RAX 0060 * @rcx (RSI) - Input parameter 1, moved to RCX 0061 * @rdx (RDX) - Input parameter 2, moved to RDX 0062 * @r8 (RCX) - Input parameter 3, moved to R8 0063 * @r9 (R8) - Input parameter 4, moved to R9 0064 * 0065 * @out (R9) - struct tdx_module_output pointer 0066 * stored temporarily in R12 (not 0067 * shared with the TDX module). It 0068 * can be NULL. 0069 * 0070 * Return status of TDCALL via RAX. 0071 */ 0072 SYM_FUNC_START(__tdx_module_call) 0073 FRAME_BEGIN 0074 TDX_MODULE_CALL host=0 0075 FRAME_END 0076 RET 0077 SYM_FUNC_END(__tdx_module_call) 0078 0079 /* 0080 * __tdx_hypercall() - Make hypercalls to a TDX VMM using TDVMCALL leaf 0081 * of TDCALL instruction 0082 * 0083 * Transforms values in function call argument struct tdx_hypercall_args @args 0084 * into the TDCALL register ABI. After TDCALL operation, VMM output is saved 0085 * back in @args. 0086 * 0087 *------------------------------------------------------------------------- 0088 * TD VMCALL ABI: 0089 *------------------------------------------------------------------------- 0090 * 0091 * Input Registers: 0092 * 0093 * RAX - TDCALL instruction leaf number (0 - TDG.VP.VMCALL) 0094 * RCX - BITMAP which controls which part of TD Guest GPR 0095 * is passed as-is to the VMM and back. 0096 * R10 - Set 0 to indicate TDCALL follows standard TDX ABI 0097 * specification. Non zero value indicates vendor 0098 * specific ABI. 0099 * R11 - VMCALL sub function number 0100 * RBX, RBP, RDI, RSI - Used to pass VMCALL sub function specific arguments. 0101 * R8-R9, R12-R15 - Same as above. 0102 * 0103 * Output Registers: 0104 * 0105 * RAX - TDCALL instruction status (Not related to hypercall 0106 * output). 0107 * R10 - Hypercall output error code. 0108 * R11-R15 - Hypercall sub function specific output values. 0109 * 0110 *------------------------------------------------------------------------- 0111 * 0112 * __tdx_hypercall() function ABI: 0113 * 0114 * @args (RDI) - struct tdx_hypercall_args for input and output 0115 * @flags (RSI) - TDX_HCALL_* flags 0116 * 0117 * On successful completion, return the hypercall error code. 0118 */ 0119 SYM_FUNC_START(__tdx_hypercall) 0120 FRAME_BEGIN 0121 0122 /* Save callee-saved GPRs as mandated by the x86_64 ABI */ 0123 push %r15 0124 push %r14 0125 push %r13 0126 push %r12 0127 0128 /* Mangle function call ABI into TDCALL ABI: */ 0129 /* Set TDCALL leaf ID (TDVMCALL (0)) in RAX */ 0130 xor %eax, %eax 0131 0132 /* Copy hypercall registers from arg struct: */ 0133 movq TDX_HYPERCALL_r10(%rdi), %r10 0134 movq TDX_HYPERCALL_r11(%rdi), %r11 0135 movq TDX_HYPERCALL_r12(%rdi), %r12 0136 movq TDX_HYPERCALL_r13(%rdi), %r13 0137 movq TDX_HYPERCALL_r14(%rdi), %r14 0138 movq TDX_HYPERCALL_r15(%rdi), %r15 0139 0140 movl $TDVMCALL_EXPOSE_REGS_MASK, %ecx 0141 0142 /* 0143 * For the idle loop STI needs to be called directly before the TDCALL 0144 * that enters idle (EXIT_REASON_HLT case). STI instruction enables 0145 * interrupts only one instruction later. If there is a window between 0146 * STI and the instruction that emulates the HALT state, there is a 0147 * chance for interrupts to happen in this window, which can delay the 0148 * HLT operation indefinitely. Since this is the not the desired 0149 * result, conditionally call STI before TDCALL. 0150 */ 0151 testq $TDX_HCALL_ISSUE_STI, %rsi 0152 jz .Lskip_sti 0153 sti 0154 .Lskip_sti: 0155 tdcall 0156 0157 /* 0158 * RAX==0 indicates a failure of the TDVMCALL mechanism itself and that 0159 * something has gone horribly wrong with the TDX module. 0160 * 0161 * The return status of the hypercall operation is in a separate 0162 * register (in R10). Hypercall errors are a part of normal operation 0163 * and are handled by callers. 0164 */ 0165 testq %rax, %rax 0166 jne .Lpanic 0167 0168 /* TDVMCALL leaf return code is in R10 */ 0169 movq %r10, %rax 0170 0171 /* Copy hypercall result registers to arg struct if needed */ 0172 testq $TDX_HCALL_HAS_OUTPUT, %rsi 0173 jz .Lout 0174 0175 movq %r10, TDX_HYPERCALL_r10(%rdi) 0176 movq %r11, TDX_HYPERCALL_r11(%rdi) 0177 movq %r12, TDX_HYPERCALL_r12(%rdi) 0178 movq %r13, TDX_HYPERCALL_r13(%rdi) 0179 movq %r14, TDX_HYPERCALL_r14(%rdi) 0180 movq %r15, TDX_HYPERCALL_r15(%rdi) 0181 .Lout: 0182 /* 0183 * Zero out registers exposed to the VMM to avoid speculative execution 0184 * with VMM-controlled values. This needs to include all registers 0185 * present in TDVMCALL_EXPOSE_REGS_MASK (except R12-R15). R12-R15 0186 * context will be restored. 0187 */ 0188 xor %r10d, %r10d 0189 xor %r11d, %r11d 0190 0191 /* Restore callee-saved GPRs as mandated by the x86_64 ABI */ 0192 pop %r12 0193 pop %r13 0194 pop %r14 0195 pop %r15 0196 0197 FRAME_END 0198 0199 RET 0200 .Lpanic: 0201 call __tdx_hypercall_failed 0202 /* __tdx_hypercall_failed never returns */ 0203 REACHABLE 0204 jmp .Lpanic 0205 SYM_FUNC_END(__tdx_hypercall)
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.1.0 LXR engine. The LXR team |
![]() ![]() |