xref: /linux/arch/x86/kvm/svm/vmenter.S (revision adac42bf42c1608f23938c03e3ca53fa6c87f337)
1199cd1d7SUros Bizjak/* SPDX-License-Identifier: GPL-2.0 */
2199cd1d7SUros Bizjak#include <linux/linkage.h>
3199cd1d7SUros Bizjak#include <asm/asm.h>
45d821386SThomas Gleixner#include <asm/asm-offsets.h>
5199cd1d7SUros Bizjak#include <asm/bitsperlong.h>
6199cd1d7SUros Bizjak#include <asm/kvm_vcpu_regs.h>
7f14eec0aSPaolo Bonzini#include <asm/nospec-branch.h>
816fdc1deSPaolo Bonzini#include "kvm-asm-offsets.h"
9199cd1d7SUros Bizjak
10199cd1d7SUros Bizjak#define WORD_SIZE (BITS_PER_LONG / 8)
11199cd1d7SUros Bizjak
12199cd1d7SUros Bizjak/* Intentionally omit RAX as it's context switched by hardware */
1316fdc1deSPaolo Bonzini#define VCPU_RCX	(SVM_vcpu_arch_regs + __VCPU_REGS_RCX * WORD_SIZE)
1416fdc1deSPaolo Bonzini#define VCPU_RDX	(SVM_vcpu_arch_regs + __VCPU_REGS_RDX * WORD_SIZE)
1516fdc1deSPaolo Bonzini#define VCPU_RBX	(SVM_vcpu_arch_regs + __VCPU_REGS_RBX * WORD_SIZE)
16199cd1d7SUros Bizjak/* Intentionally omit RSP as it's context switched by hardware */
1716fdc1deSPaolo Bonzini#define VCPU_RBP	(SVM_vcpu_arch_regs + __VCPU_REGS_RBP * WORD_SIZE)
1816fdc1deSPaolo Bonzini#define VCPU_RSI	(SVM_vcpu_arch_regs + __VCPU_REGS_RSI * WORD_SIZE)
1916fdc1deSPaolo Bonzini#define VCPU_RDI	(SVM_vcpu_arch_regs + __VCPU_REGS_RDI * WORD_SIZE)
20199cd1d7SUros Bizjak
21199cd1d7SUros Bizjak#ifdef CONFIG_X86_64
2216fdc1deSPaolo Bonzini#define VCPU_R8		(SVM_vcpu_arch_regs + __VCPU_REGS_R8  * WORD_SIZE)
2316fdc1deSPaolo Bonzini#define VCPU_R9		(SVM_vcpu_arch_regs + __VCPU_REGS_R9  * WORD_SIZE)
2416fdc1deSPaolo Bonzini#define VCPU_R10	(SVM_vcpu_arch_regs + __VCPU_REGS_R10 * WORD_SIZE)
2516fdc1deSPaolo Bonzini#define VCPU_R11	(SVM_vcpu_arch_regs + __VCPU_REGS_R11 * WORD_SIZE)
2616fdc1deSPaolo Bonzini#define VCPU_R12	(SVM_vcpu_arch_regs + __VCPU_REGS_R12 * WORD_SIZE)
2716fdc1deSPaolo Bonzini#define VCPU_R13	(SVM_vcpu_arch_regs + __VCPU_REGS_R13 * WORD_SIZE)
2816fdc1deSPaolo Bonzini#define VCPU_R14	(SVM_vcpu_arch_regs + __VCPU_REGS_R14 * WORD_SIZE)
2916fdc1deSPaolo Bonzini#define VCPU_R15	(SVM_vcpu_arch_regs + __VCPU_REGS_R15 * WORD_SIZE)
30199cd1d7SUros Bizjak#endif
31199cd1d7SUros Bizjak
32e61ab42dSPaolo Bonzini#define SVM_vmcb01_pa	(SVM_vmcb01 + KVM_VMCB_pa)
33e61ab42dSPaolo Bonzini
34135961e0SThomas Gleixner.section .noinstr.text, "ax"
35199cd1d7SUros Bizjak
369f2febf3SPaolo Bonzini.macro RESTORE_GUEST_SPEC_CTRL
379f2febf3SPaolo Bonzini	/* No need to do anything if SPEC_CTRL is unset or V_SPEC_CTRL is set */
389f2febf3SPaolo Bonzini	ALTERNATIVE_2 "", \
399f2febf3SPaolo Bonzini		"jmp 800f", X86_FEATURE_MSR_SPEC_CTRL, \
409f2febf3SPaolo Bonzini		"", X86_FEATURE_V_SPEC_CTRL
419f2febf3SPaolo Bonzini801:
429f2febf3SPaolo Bonzini.endm
439f2febf3SPaolo Bonzini.macro RESTORE_GUEST_SPEC_CTRL_BODY
449f2febf3SPaolo Bonzini800:
459f2febf3SPaolo Bonzini	/*
469f2febf3SPaolo Bonzini	 * SPEC_CTRL handling: if the guest's SPEC_CTRL value differs from the
479f2febf3SPaolo Bonzini	 * host's, write the MSR.  This is kept out-of-line so that the common
489f2febf3SPaolo Bonzini	 * case does not have to jump.
499f2febf3SPaolo Bonzini	 *
509f2febf3SPaolo Bonzini	 * IMPORTANT: To avoid RSB underflow attacks and any other nastiness,
519f2febf3SPaolo Bonzini	 * there must not be any returns or indirect branches between this code
529f2febf3SPaolo Bonzini	 * and vmentry.
539f2febf3SPaolo Bonzini	 */
549f2febf3SPaolo Bonzini	movl SVM_spec_ctrl(%_ASM_DI), %eax
559f2febf3SPaolo Bonzini	cmp PER_CPU_VAR(x86_spec_ctrl_current), %eax
569f2febf3SPaolo Bonzini	je 801b
579f2febf3SPaolo Bonzini	mov $MSR_IA32_SPEC_CTRL, %ecx
589f2febf3SPaolo Bonzini	xor %edx, %edx
599f2febf3SPaolo Bonzini	wrmsr
609f2febf3SPaolo Bonzini	jmp 801b
619f2febf3SPaolo Bonzini.endm
629f2febf3SPaolo Bonzini
639f2febf3SPaolo Bonzini.macro RESTORE_HOST_SPEC_CTRL
649f2febf3SPaolo Bonzini	/* No need to do anything if SPEC_CTRL is unset or V_SPEC_CTRL is set */
659f2febf3SPaolo Bonzini	ALTERNATIVE_2 "", \
669f2febf3SPaolo Bonzini		"jmp 900f", X86_FEATURE_MSR_SPEC_CTRL, \
679f2febf3SPaolo Bonzini		"", X86_FEATURE_V_SPEC_CTRL
689f2febf3SPaolo Bonzini901:
699f2febf3SPaolo Bonzini.endm
70*adac42bfSSean Christopherson.macro RESTORE_HOST_SPEC_CTRL_BODY spec_ctrl_intercepted:req
719f2febf3SPaolo Bonzini900:
729f2febf3SPaolo Bonzini	/* Same for after vmexit.  */
739f2febf3SPaolo Bonzini	mov $MSR_IA32_SPEC_CTRL, %ecx
749f2febf3SPaolo Bonzini
759f2febf3SPaolo Bonzini	/*
769f2febf3SPaolo Bonzini	 * Load the value that the guest had written into MSR_IA32_SPEC_CTRL,
779f2febf3SPaolo Bonzini	 * if it was not intercepted during guest execution.
789f2febf3SPaolo Bonzini	 */
79*adac42bfSSean Christopherson	cmpb $0, \spec_ctrl_intercepted
809f2febf3SPaolo Bonzini	jnz 998f
819f2febf3SPaolo Bonzini	rdmsr
829f2febf3SPaolo Bonzini	movl %eax, SVM_spec_ctrl(%_ASM_DI)
839f2febf3SPaolo Bonzini998:
849f2febf3SPaolo Bonzini
859f2febf3SPaolo Bonzini	/* Now restore the host value of the MSR if different from the guest's.  */
869f2febf3SPaolo Bonzini	movl PER_CPU_VAR(x86_spec_ctrl_current), %eax
879f2febf3SPaolo Bonzini	cmp SVM_spec_ctrl(%_ASM_DI), %eax
889f2febf3SPaolo Bonzini	je 901b
899f2febf3SPaolo Bonzini	xor %edx, %edx
909f2febf3SPaolo Bonzini	wrmsr
919f2febf3SPaolo Bonzini	jmp 901b
929f2febf3SPaolo Bonzini.endm
939f2febf3SPaolo Bonzini
949f2febf3SPaolo Bonzini
95199cd1d7SUros Bizjak/**
96199cd1d7SUros Bizjak * __svm_vcpu_run - Run a vCPU via a transition to SVM guest mode
9716fdc1deSPaolo Bonzini * @svm:	struct vcpu_svm *
989f2febf3SPaolo Bonzini * @spec_ctrl_intercepted: bool
99199cd1d7SUros Bizjak */
100199cd1d7SUros BizjakSYM_FUNC_START(__svm_vcpu_run)
101199cd1d7SUros Bizjak	push %_ASM_BP
10219597a71SSean Christopherson	mov  %_ASM_SP, %_ASM_BP
103199cd1d7SUros Bizjak#ifdef CONFIG_X86_64
104199cd1d7SUros Bizjak	push %r15
105199cd1d7SUros Bizjak	push %r14
106199cd1d7SUros Bizjak	push %r13
107199cd1d7SUros Bizjak	push %r12
108199cd1d7SUros Bizjak#else
109199cd1d7SUros Bizjak	push %edi
110199cd1d7SUros Bizjak	push %esi
111199cd1d7SUros Bizjak#endif
112199cd1d7SUros Bizjak	push %_ASM_BX
113199cd1d7SUros Bizjak
114e287bd00SPaolo Bonzini	/*
115e287bd00SPaolo Bonzini	 * Save variables needed after vmexit on the stack, in inverse
116e287bd00SPaolo Bonzini	 * order compared to when they are needed.
117e287bd00SPaolo Bonzini	 */
118e287bd00SPaolo Bonzini
1199f2febf3SPaolo Bonzini	/* Accessed directly from the stack in RESTORE_HOST_SPEC_CTRL.  */
120199cd1d7SUros Bizjak	push %_ASM_ARG2
121199cd1d7SUros Bizjak
122e287bd00SPaolo Bonzini	/* Needed to restore access to percpu variables.  */
123e287bd00SPaolo Bonzini	__ASM_SIZE(push) PER_CPU_VAR(svm_data + SD_save_area_pa)
124e287bd00SPaolo Bonzini
1259f2febf3SPaolo Bonzini	/* Finally save @svm. */
126199cd1d7SUros Bizjak	push %_ASM_ARG1
127199cd1d7SUros Bizjak
128f6d58266SPaolo Bonzini.ifnc _ASM_ARG1, _ASM_DI
1299f2febf3SPaolo Bonzini	/*
1309f2febf3SPaolo Bonzini	 * Stash @svm in RDI early. On 32-bit, arguments are in RAX, RCX
1319f2febf3SPaolo Bonzini	 * and RDX which are clobbered by RESTORE_GUEST_SPEC_CTRL.
1329f2febf3SPaolo Bonzini	 */
133f6d58266SPaolo Bonzini	mov %_ASM_ARG1, %_ASM_DI
134f6d58266SPaolo Bonzini.endif
135199cd1d7SUros Bizjak
1369f2febf3SPaolo Bonzini	/* Clobbers RAX, RCX, RDX.  */
1379f2febf3SPaolo Bonzini	RESTORE_GUEST_SPEC_CTRL
1389f2febf3SPaolo Bonzini
139e61ab42dSPaolo Bonzini	/*
140e61ab42dSPaolo Bonzini	 * Use a single vmcb (vmcb01 because it's always valid) for
141e61ab42dSPaolo Bonzini	 * context switching guest state via VMLOAD/VMSAVE, that way
142e61ab42dSPaolo Bonzini	 * the state doesn't need to be copied between vmcb01 and
143e61ab42dSPaolo Bonzini	 * vmcb02 when switching vmcbs for nested virtualization.
144e61ab42dSPaolo Bonzini	 */
145e61ab42dSPaolo Bonzini	mov SVM_vmcb01_pa(%_ASM_DI), %_ASM_AX
146e61ab42dSPaolo Bonzini1:	vmload %_ASM_AX
147e61ab42dSPaolo Bonzini2:
148e61ab42dSPaolo Bonzini
149f6d58266SPaolo Bonzini	/* Get svm->current_vmcb->pa into RAX. */
150f6d58266SPaolo Bonzini	mov SVM_current_vmcb(%_ASM_DI), %_ASM_AX
151f6d58266SPaolo Bonzini	mov KVM_VMCB_pa(%_ASM_AX), %_ASM_AX
152199cd1d7SUros Bizjak
153199cd1d7SUros Bizjak	/* Load guest registers. */
154f7ef2801SPaolo Bonzini	mov VCPU_RCX(%_ASM_DI), %_ASM_CX
155f7ef2801SPaolo Bonzini	mov VCPU_RDX(%_ASM_DI), %_ASM_DX
156f7ef2801SPaolo Bonzini	mov VCPU_RBX(%_ASM_DI), %_ASM_BX
157f7ef2801SPaolo Bonzini	mov VCPU_RBP(%_ASM_DI), %_ASM_BP
158f7ef2801SPaolo Bonzini	mov VCPU_RSI(%_ASM_DI), %_ASM_SI
159199cd1d7SUros Bizjak#ifdef CONFIG_X86_64
160f7ef2801SPaolo Bonzini	mov VCPU_R8 (%_ASM_DI),  %r8
161f7ef2801SPaolo Bonzini	mov VCPU_R9 (%_ASM_DI),  %r9
162f7ef2801SPaolo Bonzini	mov VCPU_R10(%_ASM_DI), %r10
163f7ef2801SPaolo Bonzini	mov VCPU_R11(%_ASM_DI), %r11
164f7ef2801SPaolo Bonzini	mov VCPU_R12(%_ASM_DI), %r12
165f7ef2801SPaolo Bonzini	mov VCPU_R13(%_ASM_DI), %r13
166f7ef2801SPaolo Bonzini	mov VCPU_R14(%_ASM_DI), %r14
167f7ef2801SPaolo Bonzini	mov VCPU_R15(%_ASM_DI), %r15
168199cd1d7SUros Bizjak#endif
169f7ef2801SPaolo Bonzini	mov VCPU_RDI(%_ASM_DI), %_ASM_DI
170199cd1d7SUros Bizjak
171199cd1d7SUros Bizjak	/* Enter guest mode */
172f14eec0aSPaolo Bonzini	sti
173199cd1d7SUros Bizjak
174e61ab42dSPaolo Bonzini3:	vmrun %_ASM_AX
175e61ab42dSPaolo Bonzini4:
176e61ab42dSPaolo Bonzini	cli
177199cd1d7SUros Bizjak
178e61ab42dSPaolo Bonzini	/* Pop @svm to RAX while it's the only available register. */
179199cd1d7SUros Bizjak	pop %_ASM_AX
180199cd1d7SUros Bizjak
181199cd1d7SUros Bizjak	/* Save all guest registers.  */
182199cd1d7SUros Bizjak	mov %_ASM_CX,   VCPU_RCX(%_ASM_AX)
183199cd1d7SUros Bizjak	mov %_ASM_DX,   VCPU_RDX(%_ASM_AX)
184199cd1d7SUros Bizjak	mov %_ASM_BX,   VCPU_RBX(%_ASM_AX)
185199cd1d7SUros Bizjak	mov %_ASM_BP,   VCPU_RBP(%_ASM_AX)
186199cd1d7SUros Bizjak	mov %_ASM_SI,   VCPU_RSI(%_ASM_AX)
187199cd1d7SUros Bizjak	mov %_ASM_DI,   VCPU_RDI(%_ASM_AX)
188199cd1d7SUros Bizjak#ifdef CONFIG_X86_64
189199cd1d7SUros Bizjak	mov %r8,  VCPU_R8 (%_ASM_AX)
190199cd1d7SUros Bizjak	mov %r9,  VCPU_R9 (%_ASM_AX)
191199cd1d7SUros Bizjak	mov %r10, VCPU_R10(%_ASM_AX)
192199cd1d7SUros Bizjak	mov %r11, VCPU_R11(%_ASM_AX)
193199cd1d7SUros Bizjak	mov %r12, VCPU_R12(%_ASM_AX)
194199cd1d7SUros Bizjak	mov %r13, VCPU_R13(%_ASM_AX)
195199cd1d7SUros Bizjak	mov %r14, VCPU_R14(%_ASM_AX)
196199cd1d7SUros Bizjak	mov %r15, VCPU_R15(%_ASM_AX)
197199cd1d7SUros Bizjak#endif
198199cd1d7SUros Bizjak
199e61ab42dSPaolo Bonzini	/* @svm can stay in RDI from now on.  */
200e61ab42dSPaolo Bonzini	mov %_ASM_AX, %_ASM_DI
201e61ab42dSPaolo Bonzini
202e61ab42dSPaolo Bonzini	mov SVM_vmcb01_pa(%_ASM_DI), %_ASM_AX
203e61ab42dSPaolo Bonzini5:	vmsave %_ASM_AX
204e61ab42dSPaolo Bonzini6:
205e61ab42dSPaolo Bonzini
206e287bd00SPaolo Bonzini	/* Restores GSBASE among other things, allowing access to percpu data.  */
207e287bd00SPaolo Bonzini	pop %_ASM_AX
208e287bd00SPaolo Bonzini7:	vmload %_ASM_AX
209e287bd00SPaolo Bonzini8:
210e287bd00SPaolo Bonzini
211aefb2f2eSBreno Leitao#ifdef CONFIG_MITIGATION_RETPOLINE
212e61ab42dSPaolo Bonzini	/* IMPORTANT: Stuff the RSB immediately after VM-Exit, before RET! */
213e61ab42dSPaolo Bonzini	FILL_RETURN_BUFFER %_ASM_AX, RSB_CLEAR_LOOPS, X86_FEATURE_RETPOLINE
214e61ab42dSPaolo Bonzini#endif
215e61ab42dSPaolo Bonzini
2169f2febf3SPaolo Bonzini	/* Clobbers RAX, RCX, RDX.  */
2179f2febf3SPaolo Bonzini	RESTORE_HOST_SPEC_CTRL
2189f2febf3SPaolo Bonzini
219199cd1d7SUros Bizjak	/*
220a149180fSPeter Zijlstra	 * Mitigate RETBleed for AMD/Hygon Zen uarch. RET should be
221a149180fSPeter Zijlstra	 * untrained as soon as we exit the VM and are back to the
222a149180fSPeter Zijlstra	 * kernel. This should be done before re-enabling interrupts
223a149180fSPeter Zijlstra	 * because interrupt handlers won't sanitize 'ret' if the return is
224a149180fSPeter Zijlstra	 * from the kernel.
225a149180fSPeter Zijlstra	 */
226864bcaa3SPeter Zijlstra	UNTRAIN_RET_VM
227d893832dSBorislav Petkov (AMD)
228a149180fSPeter Zijlstra	/*
229199cd1d7SUros Bizjak	 * Clear all general purpose registers except RSP and RAX to prevent
230199cd1d7SUros Bizjak	 * speculative use of the guest's values, even those that are reloaded
231199cd1d7SUros Bizjak	 * via the stack.  In theory, an L1 cache miss when restoring registers
232199cd1d7SUros Bizjak	 * could lead to speculative execution with the guest's values.
233199cd1d7SUros Bizjak	 * Zeroing XORs are dirt cheap, i.e. the extra paranoia is essentially
234199cd1d7SUros Bizjak	 * free.  RSP and RAX are exempt as they are restored by hardware
235199cd1d7SUros Bizjak	 * during VM-Exit.
236199cd1d7SUros Bizjak	 */
237199cd1d7SUros Bizjak	xor %ecx, %ecx
238199cd1d7SUros Bizjak	xor %edx, %edx
239199cd1d7SUros Bizjak	xor %ebx, %ebx
240199cd1d7SUros Bizjak	xor %ebp, %ebp
241199cd1d7SUros Bizjak	xor %esi, %esi
242199cd1d7SUros Bizjak	xor %edi, %edi
243199cd1d7SUros Bizjak#ifdef CONFIG_X86_64
244199cd1d7SUros Bizjak	xor %r8d,  %r8d
245199cd1d7SUros Bizjak	xor %r9d,  %r9d
246199cd1d7SUros Bizjak	xor %r10d, %r10d
247199cd1d7SUros Bizjak	xor %r11d, %r11d
248199cd1d7SUros Bizjak	xor %r12d, %r12d
249199cd1d7SUros Bizjak	xor %r13d, %r13d
250199cd1d7SUros Bizjak	xor %r14d, %r14d
251199cd1d7SUros Bizjak	xor %r15d, %r15d
252199cd1d7SUros Bizjak#endif
253199cd1d7SUros Bizjak
2549f2febf3SPaolo Bonzini	/* "Pop" @spec_ctrl_intercepted.  */
2559f2febf3SPaolo Bonzini	pop %_ASM_BX
2569f2febf3SPaolo Bonzini
257199cd1d7SUros Bizjak	pop %_ASM_BX
258199cd1d7SUros Bizjak
259199cd1d7SUros Bizjak#ifdef CONFIG_X86_64
260199cd1d7SUros Bizjak	pop %r12
261199cd1d7SUros Bizjak	pop %r13
262199cd1d7SUros Bizjak	pop %r14
263199cd1d7SUros Bizjak	pop %r15
264199cd1d7SUros Bizjak#else
265199cd1d7SUros Bizjak	pop %esi
266199cd1d7SUros Bizjak	pop %edi
267199cd1d7SUros Bizjak#endif
268199cd1d7SUros Bizjak	pop %_ASM_BP
269f94909ceSPeter Zijlstra	RET
2707531b47cSUros Bizjak
2719f2febf3SPaolo Bonzini	RESTORE_GUEST_SPEC_CTRL_BODY
272*adac42bfSSean Christopherson	RESTORE_HOST_SPEC_CTRL_BODY (%_ASM_SP)
2739f2febf3SPaolo Bonzini
27415223c4fSUros Bizjak10:	cmpb $0, _ASM_RIP(kvm_rebooting)
2757531b47cSUros Bizjak	jne 2b
2767531b47cSUros Bizjak	ud2
27715223c4fSUros Bizjak30:	cmpb $0, _ASM_RIP(kvm_rebooting)
278e61ab42dSPaolo Bonzini	jne 4b
279e61ab42dSPaolo Bonzini	ud2
28015223c4fSUros Bizjak50:	cmpb $0, _ASM_RIP(kvm_rebooting)
281e61ab42dSPaolo Bonzini	jne 6b
282e61ab42dSPaolo Bonzini	ud2
28315223c4fSUros Bizjak70:	cmpb $0, _ASM_RIP(kvm_rebooting)
284e287bd00SPaolo Bonzini	jne 8b
285e287bd00SPaolo Bonzini	ud2
2867531b47cSUros Bizjak
287e61ab42dSPaolo Bonzini	_ASM_EXTABLE(1b, 10b)
288e61ab42dSPaolo Bonzini	_ASM_EXTABLE(3b, 30b)
289e61ab42dSPaolo Bonzini	_ASM_EXTABLE(5b, 50b)
290e287bd00SPaolo Bonzini	_ASM_EXTABLE(7b, 70b)
2917531b47cSUros Bizjak
292199cd1d7SUros BizjakSYM_FUNC_END(__svm_vcpu_run)
29316809ecdSTom Lendacky
2947774c8f3SSean Christopherson#ifdef CONFIG_KVM_AMD_SEV
295c92be2fdSSean Christopherson
296c92be2fdSSean Christopherson
297c92be2fdSSean Christopherson#ifdef CONFIG_X86_64
298c92be2fdSSean Christopherson#define SEV_ES_GPRS_BASE 0x300
299c92be2fdSSean Christopherson#define SEV_ES_RBX	(SEV_ES_GPRS_BASE + __VCPU_REGS_RBX * WORD_SIZE)
300c92be2fdSSean Christopherson#define SEV_ES_RBP	(SEV_ES_GPRS_BASE + __VCPU_REGS_RBP * WORD_SIZE)
301*adac42bfSSean Christopherson#define SEV_ES_RSI	(SEV_ES_GPRS_BASE + __VCPU_REGS_RSI * WORD_SIZE)
302*adac42bfSSean Christopherson#define SEV_ES_RDI	(SEV_ES_GPRS_BASE + __VCPU_REGS_RDI * WORD_SIZE)
303c92be2fdSSean Christopherson#define SEV_ES_R12	(SEV_ES_GPRS_BASE + __VCPU_REGS_R12 * WORD_SIZE)
304c92be2fdSSean Christopherson#define SEV_ES_R13	(SEV_ES_GPRS_BASE + __VCPU_REGS_R13 * WORD_SIZE)
305c92be2fdSSean Christopherson#define SEV_ES_R14	(SEV_ES_GPRS_BASE + __VCPU_REGS_R14 * WORD_SIZE)
306c92be2fdSSean Christopherson#define SEV_ES_R15	(SEV_ES_GPRS_BASE + __VCPU_REGS_R15 * WORD_SIZE)
307c92be2fdSSean Christopherson#endif
308c92be2fdSSean Christopherson
30916809ecdSTom Lendacky/**
31016809ecdSTom Lendacky * __svm_sev_es_vcpu_run - Run a SEV-ES vCPU via a transition to SVM guest mode
311f6d58266SPaolo Bonzini * @svm:	struct vcpu_svm *
3129f2febf3SPaolo Bonzini * @spec_ctrl_intercepted: bool
31316809ecdSTom Lendacky */
31416809ecdSTom LendackySYM_FUNC_START(__svm_sev_es_vcpu_run)
3159f2febf3SPaolo Bonzini	/*
316c92be2fdSSean Christopherson	 * Save non-volatile (callee-saved) registers to the host save area.
317c92be2fdSSean Christopherson	 * Except for RAX and RSP, all GPRs are restored on #VMEXIT, but not
318c92be2fdSSean Christopherson	 * saved on VMRUN.
3199f2febf3SPaolo Bonzini	 */
320c92be2fdSSean Christopherson	mov %rbp, SEV_ES_RBP (%rdx)
321c92be2fdSSean Christopherson	mov %r15, SEV_ES_R15 (%rdx)
322c92be2fdSSean Christopherson	mov %r14, SEV_ES_R14 (%rdx)
323c92be2fdSSean Christopherson	mov %r13, SEV_ES_R13 (%rdx)
324c92be2fdSSean Christopherson	mov %r12, SEV_ES_R12 (%rdx)
325c92be2fdSSean Christopherson	mov %rbx, SEV_ES_RBX (%rdx)
3269f2febf3SPaolo Bonzini
327*adac42bfSSean Christopherson	/*
328*adac42bfSSean Christopherson	 * Save volatile registers that hold arguments that are needed after
329*adac42bfSSean Christopherson	 * #VMEXIT (RDI=@svm and RSI=@spec_ctrl_intercepted).
330*adac42bfSSean Christopherson	 */
331*adac42bfSSean Christopherson	mov %rdi, SEV_ES_RDI (%rdx)
332*adac42bfSSean Christopherson	mov %rsi, SEV_ES_RSI (%rdx)
3339f2febf3SPaolo Bonzini
334c92be2fdSSean Christopherson	/* Clobbers RAX, RCX, RDX (@hostsa). */
3359f2febf3SPaolo Bonzini	RESTORE_GUEST_SPEC_CTRL
3369f2febf3SPaolo Bonzini
337f6d58266SPaolo Bonzini	/* Get svm->current_vmcb->pa into RAX. */
338331282fdSSean Christopherson	mov SVM_current_vmcb(%rdi), %rax
339331282fdSSean Christopherson	mov KVM_VMCB_pa(%rax), %rax
3407531b47cSUros Bizjak
3417531b47cSUros Bizjak	/* Enter guest mode */
34216809ecdSTom Lendacky	sti
34316809ecdSTom Lendacky
344331282fdSSean Christopherson1:	vmrun %rax
34516809ecdSTom Lendacky
3467531b47cSUros Bizjak2:	cli
34716809ecdSTom Lendacky
348aefb2f2eSBreno Leitao#ifdef CONFIG_MITIGATION_RETPOLINE
34916809ecdSTom Lendacky	/* IMPORTANT: Stuff the RSB immediately after VM-Exit, before RET! */
350331282fdSSean Christopherson	FILL_RETURN_BUFFER %rax, RSB_CLEAR_LOOPS, X86_FEATURE_RETPOLINE
35116809ecdSTom Lendacky#endif
35216809ecdSTom Lendacky
353*adac42bfSSean Christopherson	/* Clobbers RAX, RCX, RDX, consumes RDI (@svm) and RSI (@spec_ctrl_intercepted). */
3549f2febf3SPaolo Bonzini	RESTORE_HOST_SPEC_CTRL
3559f2febf3SPaolo Bonzini
356a149180fSPeter Zijlstra	/*
357a149180fSPeter Zijlstra	 * Mitigate RETBleed for AMD/Hygon Zen uarch. RET should be
358a149180fSPeter Zijlstra	 * untrained as soon as we exit the VM and are back to the
359a149180fSPeter Zijlstra	 * kernel. This should be done before re-enabling interrupts
360a149180fSPeter Zijlstra	 * because interrupt handlers won't sanitize RET if the return is
361a149180fSPeter Zijlstra	 * from the kernel.
362a149180fSPeter Zijlstra	 */
363864bcaa3SPeter Zijlstra	UNTRAIN_RET_VM
364a149180fSPeter Zijlstra
365f94909ceSPeter Zijlstra	RET
3667531b47cSUros Bizjak
3679f2febf3SPaolo Bonzini	RESTORE_GUEST_SPEC_CTRL_BODY
368*adac42bfSSean Christopherson	RESTORE_HOST_SPEC_CTRL_BODY %sil
3699f2febf3SPaolo Bonzini
370331282fdSSean Christopherson3:	cmpb $0, kvm_rebooting(%rip)
3717531b47cSUros Bizjak	jne 2b
3727531b47cSUros Bizjak	ud2
3737531b47cSUros Bizjak
3747531b47cSUros Bizjak	_ASM_EXTABLE(1b, 3b)
3757531b47cSUros Bizjak
37616809ecdSTom LendackySYM_FUNC_END(__svm_sev_es_vcpu_run)
3777774c8f3SSean Christopherson#endif /* CONFIG_KVM_AMD_SEV */
378