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