xref: /linux/arch/x86/kvm/vmenter.h (revision c3029c38175b66b8ed8713f6c6c028a1de998b0d)
1bfac263fSPaolo Bonzini /* SPDX-License-Identifier: GPL-2.0 */
2bfac263fSPaolo Bonzini #ifndef __KVM_X86_VMENTER_H
3bfac263fSPaolo Bonzini #define __KVM_X86_VMENTER_H
4bfac263fSPaolo Bonzini 
5*c3029c38SChang S. Bae #include <asm/kvm_vcpu_regs.h>
6*c3029c38SChang S. Bae 
7bfac263fSPaolo Bonzini #define KVM_ENTER_VMRESUME			BIT(0)
8bfac263fSPaolo Bonzini #define KVM_ENTER_SAVE_SPEC_CTRL		BIT(1)
9bfac263fSPaolo Bonzini #define KVM_ENTER_CLEAR_CPU_BUFFERS_FOR_MMIO	BIT(2)
10bfac263fSPaolo Bonzini 
114b275d0fSPaolo Bonzini #ifdef __ASSEMBLER__
124b275d0fSPaolo Bonzini .macro RESTORE_GUEST_SPEC_CTRL_BODY guest_spec_ctrl:req, label:req
134b275d0fSPaolo Bonzini 	/*
144b275d0fSPaolo Bonzini 	 * SPEC_CTRL handling: if the guest's SPEC_CTRL value differs from the
154b275d0fSPaolo Bonzini 	 * host's, write the MSR.  This is kept out-of-line so that the common
164b275d0fSPaolo Bonzini 	 * case does not have to jump.
174b275d0fSPaolo Bonzini 	 *
184b275d0fSPaolo Bonzini 	 * IMPORTANT: To avoid RSB underflow attacks and any other nastiness,
194b275d0fSPaolo Bonzini 	 * there must not be any returns or indirect branches between this code
204b275d0fSPaolo Bonzini 	 * and vmentry.
214b275d0fSPaolo Bonzini 	 */
224b275d0fSPaolo Bonzini #ifdef CONFIG_X86_64
234b275d0fSPaolo Bonzini 	mov \guest_spec_ctrl, %rdx
244b275d0fSPaolo Bonzini 	cmp PER_CPU_VAR(x86_spec_ctrl_current), %rdx
254b275d0fSPaolo Bonzini 	je \label
264b275d0fSPaolo Bonzini 	movl %edx, %eax
274b275d0fSPaolo Bonzini 	shr $32, %rdx
284b275d0fSPaolo Bonzini #else
294b275d0fSPaolo Bonzini 	mov \guest_spec_ctrl, %eax
304b275d0fSPaolo Bonzini 	mov PER_CPU_VAR(x86_spec_ctrl_current), %ecx
314b275d0fSPaolo Bonzini 	xor %eax, %ecx
324b275d0fSPaolo Bonzini 	mov 4 + \guest_spec_ctrl, %edx
334b275d0fSPaolo Bonzini 	mov PER_CPU_VAR(x86_spec_ctrl_current + 4), %esi
344b275d0fSPaolo Bonzini 	xor %edx, %esi
354b275d0fSPaolo Bonzini 	or %esi, %ecx
364b275d0fSPaolo Bonzini 	je \label
374b275d0fSPaolo Bonzini #endif
384b275d0fSPaolo Bonzini 	mov $MSR_IA32_SPEC_CTRL, %ecx
394b275d0fSPaolo Bonzini 	wrmsr
404b275d0fSPaolo Bonzini .endm
414b275d0fSPaolo Bonzini 
424b275d0fSPaolo Bonzini .macro RESTORE_HOST_SPEC_CTRL_BODY guest_spec_ctrl:req, enter_flags:req, label:req
434b275d0fSPaolo Bonzini 	/* Same for after vmexit.  */
444b275d0fSPaolo Bonzini 	mov $MSR_IA32_SPEC_CTRL, %ecx
454b275d0fSPaolo Bonzini 
464b275d0fSPaolo Bonzini 	/*
474b275d0fSPaolo Bonzini 	 * Load the value that the guest had written into MSR_IA32_SPEC_CTRL,
484b275d0fSPaolo Bonzini 	 * if it was not intercepted during guest execution.
494b275d0fSPaolo Bonzini 	 */
504b275d0fSPaolo Bonzini 	testl $KVM_ENTER_SAVE_SPEC_CTRL, \enter_flags
514b275d0fSPaolo Bonzini 	jz 998f
524b275d0fSPaolo Bonzini 	rdmsr
534b275d0fSPaolo Bonzini 	movl %eax, \guest_spec_ctrl
544b275d0fSPaolo Bonzini 	movl %edx, 4 + \guest_spec_ctrl
554b275d0fSPaolo Bonzini 998:
564b275d0fSPaolo Bonzini 	/* Now restore the host value of the MSR if different from the guest's.  */
574b275d0fSPaolo Bonzini #ifdef CONFIG_X86_64
584b275d0fSPaolo Bonzini 	mov PER_CPU_VAR(x86_spec_ctrl_current), %rdx
594b275d0fSPaolo Bonzini 	cmp \guest_spec_ctrl, %rdx
60344ebd21SPaolo Bonzini 	/*
61344ebd21SPaolo Bonzini 	 * For legacy IBRS, the IBRS bit always needs to be written after
62344ebd21SPaolo Bonzini 	 * transitioning from a less privileged predictor mode, regardless of
63344ebd21SPaolo Bonzini 	 * whether the guest/host values differ.
64344ebd21SPaolo Bonzini 	 */
65344ebd21SPaolo Bonzini 	ALTERNATIVE __stringify(je \label), "", X86_FEATURE_KERNEL_IBRS
664b275d0fSPaolo Bonzini 	movl %edx, %eax
674b275d0fSPaolo Bonzini 	shr $32, %rdx
684b275d0fSPaolo Bonzini #else
694b275d0fSPaolo Bonzini 	mov PER_CPU_VAR(x86_spec_ctrl_current), %eax
704b275d0fSPaolo Bonzini 	mov \guest_spec_ctrl, %esi
714b275d0fSPaolo Bonzini 	xor %eax, %esi
724b275d0fSPaolo Bonzini 	mov PER_CPU_VAR(x86_spec_ctrl_current + 4), %edx
734b275d0fSPaolo Bonzini 	mov 4 + \guest_spec_ctrl, %edi
744b275d0fSPaolo Bonzini 	xor %edx, %edi
754b275d0fSPaolo Bonzini 	or %edi, %esi
76344ebd21SPaolo Bonzini 	ALTERNATIVE __stringify(je \label), "", X86_FEATURE_KERNEL_IBRS
774b275d0fSPaolo Bonzini #endif
784b275d0fSPaolo Bonzini 	wrmsr
794b275d0fSPaolo Bonzini .endm
804b275d0fSPaolo Bonzini 
81*c3029c38SChang S. Bae #define WORD_SIZE (BITS_PER_LONG / 8)
82*c3029c38SChang S. Bae 
83*c3029c38SChang S. Bae .macro LOAD_REGS src:req, regs_ofs:req, regs:vararg
84*c3029c38SChang S. Bae .irp reg, \regs
85*c3029c38SChang S. Bae 	REG_NUM reg_num \reg
86*c3029c38SChang S. Bae 	mov (\regs_ofs + reg_num * WORD_SIZE)(\src), \reg
87*c3029c38SChang S. Bae .endr
88*c3029c38SChang S. Bae .endm
89*c3029c38SChang S. Bae 
90*c3029c38SChang S. Bae .macro STORE_REGS dst:req, regs_ofs:req, regs:vararg
91*c3029c38SChang S. Bae .irp reg, \regs
92*c3029c38SChang S. Bae 	REG_NUM reg_num \reg
93*c3029c38SChang S. Bae 	mov \reg, (\regs_ofs + reg_num * WORD_SIZE)(\dst)
94*c3029c38SChang S. Bae .endr
95*c3029c38SChang S. Bae .endm
96*c3029c38SChang S. Bae 
97*c3029c38SChang S. Bae .macro POP_REGS dst:req, regs_ofs:req, regs:vararg
98*c3029c38SChang S. Bae .irp reg, \regs
99*c3029c38SChang S. Bae 	REG_NUM reg_num \reg
100*c3029c38SChang S. Bae 	pop (\regs_ofs + reg_num * WORD_SIZE)(\dst)
101*c3029c38SChang S. Bae .endr
102*c3029c38SChang S. Bae .endm
103*c3029c38SChang S. Bae 
104*c3029c38SChang S. Bae .macro CLEAR_REGS regs:vararg
105*c3029c38SChang S. Bae .irp reg, \regs
106*c3029c38SChang S. Bae 	xorl \reg, \reg
107*c3029c38SChang S. Bae .endr
108*c3029c38SChang S. Bae .endm
109*c3029c38SChang S. Bae 
1104b275d0fSPaolo Bonzini #endif /* __ASSEMBLER__ */
111bfac263fSPaolo Bonzini #endif /* __KVM_X86_VMENTER_H */
112