Linux Audio

Check our new training course

Loading...
v6.2
  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)
v6.2
  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)