File Index
Files and directories
Sign in
FILE

vmenter.S

File preview with syntax highlighting.

linux-6.19.14/arch/x86/kvm/svm/vmenter.S GAS
  1/* SPDX-License-Identifier: GPL-2.0 */
  2#include <linux/linkage.h>
  3#include <asm/asm.h>
  4#include <asm/asm-offsets.h>
  5#include <asm/bitsperlong.h>
  6#include <asm/frame.h>
  7#include <asm/kvm_vcpu_regs.h>
  8#include <asm/nospec-branch.h>
  9#include "kvm-asm-offsets.h"
 10
 11#define WORD_SIZE (BITS_PER_LONG / 8)
 12
 13/* Intentionally omit RAX as it's context switched by hardware */
 14#define VCPU_RCX	(SVM_vcpu_arch_regs + __VCPU_REGS_RCX * WORD_SIZE)
 15#define VCPU_RDX	(SVM_vcpu_arch_regs + __VCPU_REGS_RDX * WORD_SIZE)
 16#define VCPU_RBX	(SVM_vcpu_arch_regs + __VCPU_REGS_RBX * WORD_SIZE)
 17/* Intentionally omit RSP as it's context switched by hardware */
 18#define VCPU_RBP	(SVM_vcpu_arch_regs + __VCPU_REGS_RBP * WORD_SIZE)
 19#define VCPU_RSI	(SVM_vcpu_arch_regs + __VCPU_REGS_RSI * WORD_SIZE)
 20#define VCPU_RDI	(SVM_vcpu_arch_regs + __VCPU_REGS_RDI * WORD_SIZE)
 21
 22#ifdef CONFIG_X86_64
 23#define VCPU_R8		(SVM_vcpu_arch_regs + __VCPU_REGS_R8  * WORD_SIZE)
 24#define VCPU_R9		(SVM_vcpu_arch_regs + __VCPU_REGS_R9  * WORD_SIZE)
 25#define VCPU_R10	(SVM_vcpu_arch_regs + __VCPU_REGS_R10 * WORD_SIZE)
 26#define VCPU_R11	(SVM_vcpu_arch_regs + __VCPU_REGS_R11 * WORD_SIZE)
 27#define VCPU_R12	(SVM_vcpu_arch_regs + __VCPU_REGS_R12 * WORD_SIZE)
 28#define VCPU_R13	(SVM_vcpu_arch_regs + __VCPU_REGS_R13 * WORD_SIZE)
 29#define VCPU_R14	(SVM_vcpu_arch_regs + __VCPU_REGS_R14 * WORD_SIZE)
 30#define VCPU_R15	(SVM_vcpu_arch_regs + __VCPU_REGS_R15 * WORD_SIZE)
 31#endif
 32
 33#define SVM_vmcb01_pa	(SVM_vmcb01 + KVM_VMCB_pa)
 34
 35.section .noinstr.text, "ax"
 36
 37.macro RESTORE_GUEST_SPEC_CTRL
 38	/* No need to do anything if SPEC_CTRL is unset or V_SPEC_CTRL is set */
 39	ALTERNATIVE_2 "", \
 40		"jmp 800f", X86_FEATURE_MSR_SPEC_CTRL, \
 41		"", X86_FEATURE_V_SPEC_CTRL
 42801:
 43.endm
 44.macro RESTORE_GUEST_SPEC_CTRL_BODY
 45800:
 46	/*
 47	 * SPEC_CTRL handling: if the guest's SPEC_CTRL value differs from the
 48	 * host's, write the MSR.  This is kept out-of-line so that the common
 49	 * case does not have to jump.
 50	 *
 51	 * IMPORTANT: To avoid RSB underflow attacks and any other nastiness,
 52	 * there must not be any returns or indirect branches between this code
 53	 * and vmentry.
 54	 */
 55#ifdef CONFIG_X86_64
 56	mov SVM_spec_ctrl(%rdi), %rdx
 57	cmp PER_CPU_VAR(x86_spec_ctrl_current), %rdx
 58	je 801b
 59	movl %edx, %eax
 60	shr $32, %rdx
 61#else
 62	mov SVM_spec_ctrl(%edi), %eax
 63	mov PER_CPU_VAR(x86_spec_ctrl_current), %ecx
 64	xor %eax, %ecx
 65	mov SVM_spec_ctrl + 4(%edi), %edx
 66	mov PER_CPU_VAR(x86_spec_ctrl_current + 4), %esi
 67	xor %edx, %esi
 68	or %esi, %ecx
 69	je 801b
 70#endif
 71	mov $MSR_IA32_SPEC_CTRL, %ecx
 72	wrmsr
 73	jmp 801b
 74.endm
 75
 76.macro RESTORE_HOST_SPEC_CTRL
 77	/* No need to do anything if SPEC_CTRL is unset or V_SPEC_CTRL is set */
 78	ALTERNATIVE_2 "", \
 79		"jmp 900f", X86_FEATURE_MSR_SPEC_CTRL, \
 80		"", X86_FEATURE_V_SPEC_CTRL
 81901:
 82.endm
 83.macro RESTORE_HOST_SPEC_CTRL_BODY spec_ctrl_intercepted:req
 84900:
 85	/* Same for after vmexit.  */
 86	mov $MSR_IA32_SPEC_CTRL, %ecx
 87
 88	/*
 89	 * Load the value that the guest had written into MSR_IA32_SPEC_CTRL,
 90	 * if it was not intercepted during guest execution.
 91	 */
 92	cmpb $0, \spec_ctrl_intercepted
 93	jnz 998f
 94	rdmsr
 95	movl %eax, SVM_spec_ctrl(%_ASM_DI)
 96	movl %edx, SVM_spec_ctrl + 4(%_ASM_DI)
 97998:
 98	/* Now restore the host value of the MSR if different from the guest's.  */
 99#ifdef CONFIG_X86_64
100	mov PER_CPU_VAR(x86_spec_ctrl_current), %rdx
101	cmp SVM_spec_ctrl(%rdi), %rdx
102	je 901b
103	movl %edx, %eax
104	shr $32, %rdx
105#else
106	mov PER_CPU_VAR(x86_spec_ctrl_current), %eax
107	mov SVM_spec_ctrl(%edi), %esi
108	xor %eax, %esi
109	mov PER_CPU_VAR(x86_spec_ctrl_current + 4), %edx
110	mov SVM_spec_ctrl + 4(%edi), %edi
111	xor %edx, %edi
112	or %edi, %esi
113	je 901b
114#endif
115	wrmsr
116	jmp 901b
117.endm
118
119#define SVM_CLEAR_CPU_BUFFERS \
120	ALTERNATIVE "", __CLEAR_CPU_BUFFERS, X86_FEATURE_CLEAR_CPU_BUF_VM
121
122/**
123 * __svm_vcpu_run - Run a vCPU via a transition to SVM guest mode
124 * @svm:	struct vcpu_svm *
125 * @spec_ctrl_intercepted: bool
126 */
127SYM_FUNC_START(__svm_vcpu_run)
128	push %_ASM_BP
129	mov  %_ASM_SP, %_ASM_BP
130#ifdef CONFIG_X86_64
131	push %r15
132	push %r14
133	push %r13
134	push %r12
135#else
136	push %edi
137	push %esi
138#endif
139	push %_ASM_BX
140
141	/*
142	 * Save variables needed after vmexit on the stack, in inverse
143	 * order compared to when they are needed.
144	 */
145
146	/* Accessed directly from the stack in RESTORE_HOST_SPEC_CTRL.  */
147	push %_ASM_ARG2
148
149	/* Needed to restore access to percpu variables.  */
150	__ASM_SIZE(push) PER_CPU_VAR(svm_data + SD_save_area_pa)
151
152	/* Finally save @svm. */
153	push %_ASM_ARG1
154
155.ifnc _ASM_ARG1, _ASM_DI
156	/*
157	 * Stash @svm in RDI early. On 32-bit, arguments are in RAX, RCX
158	 * and RDX which are clobbered by RESTORE_GUEST_SPEC_CTRL.
159	 */
160	mov %_ASM_ARG1, %_ASM_DI
161.endif
162
163	/* Clobbers RAX, RCX, RDX (and ESI on 32-bit), consumes RDI (@svm). */
164	RESTORE_GUEST_SPEC_CTRL
165
166	/*
167	 * Use a single vmcb (vmcb01 because it's always valid) for
168	 * context switching guest state via VMLOAD/VMSAVE, that way
169	 * the state doesn't need to be copied between vmcb01 and
170	 * vmcb02 when switching vmcbs for nested virtualization.
171	 */
172	mov SVM_vmcb01_pa(%_ASM_DI), %_ASM_AX
1731:	vmload %_ASM_AX
1742:
175
176	/* Get svm->current_vmcb->pa into RAX. */
177	mov SVM_current_vmcb(%_ASM_DI), %_ASM_AX
178	mov KVM_VMCB_pa(%_ASM_AX), %_ASM_AX
179
180	/* Load guest registers. */
181	mov VCPU_RCX(%_ASM_DI), %_ASM_CX
182	mov VCPU_RDX(%_ASM_DI), %_ASM_DX
183	mov VCPU_RBX(%_ASM_DI), %_ASM_BX
184	mov VCPU_RBP(%_ASM_DI), %_ASM_BP
185	mov VCPU_RSI(%_ASM_DI), %_ASM_SI
186#ifdef CONFIG_X86_64
187	mov VCPU_R8 (%_ASM_DI),  %r8
188	mov VCPU_R9 (%_ASM_DI),  %r9
189	mov VCPU_R10(%_ASM_DI), %r10
190	mov VCPU_R11(%_ASM_DI), %r11
191	mov VCPU_R12(%_ASM_DI), %r12
192	mov VCPU_R13(%_ASM_DI), %r13
193	mov VCPU_R14(%_ASM_DI), %r14
194	mov VCPU_R15(%_ASM_DI), %r15
195#endif
196	mov VCPU_RDI(%_ASM_DI), %_ASM_DI
197
198	/* Clobbers EFLAGS.ZF */
199	SVM_CLEAR_CPU_BUFFERS
200
201	/* Enter guest mode */
2023:	vmrun %_ASM_AX
2034:
204	/* Pop @svm to RAX while it's the only available register. */
205	pop %_ASM_AX
206
207	/* Save all guest registers.  */
208	mov %_ASM_CX,   VCPU_RCX(%_ASM_AX)
209	mov %_ASM_DX,   VCPU_RDX(%_ASM_AX)
210	mov %_ASM_BX,   VCPU_RBX(%_ASM_AX)
211	mov %_ASM_BP,   VCPU_RBP(%_ASM_AX)
212	mov %_ASM_SI,   VCPU_RSI(%_ASM_AX)
213	mov %_ASM_DI,   VCPU_RDI(%_ASM_AX)
214#ifdef CONFIG_X86_64
215	mov %r8,  VCPU_R8 (%_ASM_AX)
216	mov %r9,  VCPU_R9 (%_ASM_AX)
217	mov %r10, VCPU_R10(%_ASM_AX)
218	mov %r11, VCPU_R11(%_ASM_AX)
219	mov %r12, VCPU_R12(%_ASM_AX)
220	mov %r13, VCPU_R13(%_ASM_AX)
221	mov %r14, VCPU_R14(%_ASM_AX)
222	mov %r15, VCPU_R15(%_ASM_AX)
223#endif
224
225	/* @svm can stay in RDI from now on.  */
226	mov %_ASM_AX, %_ASM_DI
227
228	mov SVM_vmcb01_pa(%_ASM_DI), %_ASM_AX
2295:	vmsave %_ASM_AX
2306:
231
232	/* Restores GSBASE among other things, allowing access to percpu data.  */
233	pop %_ASM_AX
2347:	vmload %_ASM_AX
2358:
236
237	/* IMPORTANT: Stuff the RSB immediately after VM-Exit, before RET! */
238	FILL_RETURN_BUFFER %_ASM_AX, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_VMEXIT
239
240	/*
241	 * Clobbers RAX, RCX, RDX (and ESI, EDI on 32-bit), consumes RDI (@svm)
242	 * and RSP (pointer to @spec_ctrl_intercepted).
243	 */
244	RESTORE_HOST_SPEC_CTRL
245
246	/*
247	 * Mitigate RETBleed for AMD/Hygon Zen uarch. RET should be
248	 * untrained as soon as we exit the VM and are back to the
249	 * kernel. This should be done before re-enabling interrupts
250	 * because interrupt handlers won't sanitize 'ret' if the return is
251	 * from the kernel.
252	 */
253	UNTRAIN_RET_VM
254
255	/*
256	 * Clear all general purpose registers except RSP and RAX to prevent
257	 * speculative use of the guest's values, even those that are reloaded
258	 * via the stack.  In theory, an L1 cache miss when restoring registers
259	 * could lead to speculative execution with the guest's values.
260	 * Zeroing XORs are dirt cheap, i.e. the extra paranoia is essentially
261	 * free.  RSP and RAX are exempt as they are restored by hardware
262	 * during VM-Exit.
263	 */
264	xor %ecx, %ecx
265	xor %edx, %edx
266	xor %ebx, %ebx
267	xor %ebp, %ebp
268	xor %esi, %esi
269	xor %edi, %edi
270#ifdef CONFIG_X86_64
271	xor %r8d,  %r8d
272	xor %r9d,  %r9d
273	xor %r10d, %r10d
274	xor %r11d, %r11d
275	xor %r12d, %r12d
276	xor %r13d, %r13d
277	xor %r14d, %r14d
278	xor %r15d, %r15d
279#endif
280
281	/* "Pop" @spec_ctrl_intercepted.  */
282	pop %_ASM_BX
283
284	pop %_ASM_BX
285
286#ifdef CONFIG_X86_64
287	pop %r12
288	pop %r13
289	pop %r14
290	pop %r15
291#else
292	pop %esi
293	pop %edi
294#endif
295	pop %_ASM_BP
296	RET
297
298	RESTORE_GUEST_SPEC_CTRL_BODY
299	RESTORE_HOST_SPEC_CTRL_BODY (%_ASM_SP)
300
30110:	cmpb $0, _ASM_RIP(kvm_rebooting)
302	jne 2b
303	ud2
30430:	cmpb $0, _ASM_RIP(kvm_rebooting)
305	jne 4b
306	ud2
30750:	cmpb $0, _ASM_RIP(kvm_rebooting)
308	jne 6b
309	ud2
31070:	cmpb $0, _ASM_RIP(kvm_rebooting)
311	jne 8b
312	ud2
313
314	_ASM_EXTABLE(1b, 10b)
315	_ASM_EXTABLE(3b, 30b)
316	_ASM_EXTABLE(5b, 50b)
317	_ASM_EXTABLE(7b, 70b)
318
319SYM_FUNC_END(__svm_vcpu_run)
320
321#ifdef CONFIG_KVM_AMD_SEV
322
323
324#ifdef CONFIG_X86_64
325#define SEV_ES_GPRS_BASE 0x300
326#define SEV_ES_RBX	(SEV_ES_GPRS_BASE + __VCPU_REGS_RBX * WORD_SIZE)
327#define SEV_ES_RBP	(SEV_ES_GPRS_BASE + __VCPU_REGS_RBP * WORD_SIZE)
328#define SEV_ES_RSI	(SEV_ES_GPRS_BASE + __VCPU_REGS_RSI * WORD_SIZE)
329#define SEV_ES_RDI	(SEV_ES_GPRS_BASE + __VCPU_REGS_RDI * WORD_SIZE)
330#define SEV_ES_R12	(SEV_ES_GPRS_BASE + __VCPU_REGS_R12 * WORD_SIZE)
331#define SEV_ES_R13	(SEV_ES_GPRS_BASE + __VCPU_REGS_R13 * WORD_SIZE)
332#define SEV_ES_R14	(SEV_ES_GPRS_BASE + __VCPU_REGS_R14 * WORD_SIZE)
333#define SEV_ES_R15	(SEV_ES_GPRS_BASE + __VCPU_REGS_R15 * WORD_SIZE)
334#endif
335
336/**
337 * __svm_sev_es_vcpu_run - Run a SEV-ES vCPU via a transition to SVM guest mode
338 * @svm:	struct vcpu_svm *
339 * @spec_ctrl_intercepted: bool
340 */
341SYM_FUNC_START(__svm_sev_es_vcpu_run)
342	FRAME_BEGIN
343
344	/*
345	 * Save non-volatile (callee-saved) registers to the host save area.
346	 * Except for RAX and RSP, all GPRs are restored on #VMEXIT, but not
347	 * saved on VMRUN.
348	 */
349	mov %rbp, SEV_ES_RBP (%rdx)
350	mov %r15, SEV_ES_R15 (%rdx)
351	mov %r14, SEV_ES_R14 (%rdx)
352	mov %r13, SEV_ES_R13 (%rdx)
353	mov %r12, SEV_ES_R12 (%rdx)
354	mov %rbx, SEV_ES_RBX (%rdx)
355
356	/*
357	 * Save volatile registers that hold arguments that are needed after
358	 * #VMEXIT (RDI=@svm and RSI=@spec_ctrl_intercepted).
359	 */
360	mov %rdi, SEV_ES_RDI (%rdx)
361	mov %rsi, SEV_ES_RSI (%rdx)
362
363	/* Clobbers RAX, RCX, and RDX (@hostsa), consumes RDI (@svm). */
364	RESTORE_GUEST_SPEC_CTRL
365
366	/* Get svm->current_vmcb->pa into RAX. */
367	mov SVM_current_vmcb(%rdi), %rax
368	mov KVM_VMCB_pa(%rax), %rax
369
370	/* Clobbers EFLAGS.ZF */
371	SVM_CLEAR_CPU_BUFFERS
372
373	/* Enter guest mode */
3741:	vmrun %rax
3752:
376	/* IMPORTANT: Stuff the RSB immediately after VM-Exit, before RET! */
377	FILL_RETURN_BUFFER %rax, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_VMEXIT
378
379	/* Clobbers RAX, RCX, RDX, consumes RDI (@svm) and RSI (@spec_ctrl_intercepted). */
380	RESTORE_HOST_SPEC_CTRL
381
382	/*
383	 * Mitigate RETBleed for AMD/Hygon Zen uarch. RET should be
384	 * untrained as soon as we exit the VM and are back to the
385	 * kernel. This should be done before re-enabling interrupts
386	 * because interrupt handlers won't sanitize RET if the return is
387	 * from the kernel.
388	 */
389	UNTRAIN_RET_VM
390
391	FRAME_END
392	RET
393
394	RESTORE_GUEST_SPEC_CTRL_BODY
395	RESTORE_HOST_SPEC_CTRL_BODY %sil
396
3973:	cmpb $0, kvm_rebooting(%rip)
398	jne 2b
399	ud2
400
401	_ASM_EXTABLE(1b, 3b)
402
403SYM_FUNC_END(__svm_sev_es_vcpu_run)
404#endif /* CONFIG_KVM_AMD_SEV */
~/ Read-only file preview.