cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

tdcall.S (6430B)


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