xref: /linux/arch/x86/kvm/vmenter.h (revision c3029c38175b66b8ed8713f6c6c028a1de998b0d)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef __KVM_X86_VMENTER_H
3 #define __KVM_X86_VMENTER_H
4 
5 #include <asm/kvm_vcpu_regs.h>
6 
7 #define KVM_ENTER_VMRESUME			BIT(0)
8 #define KVM_ENTER_SAVE_SPEC_CTRL		BIT(1)
9 #define KVM_ENTER_CLEAR_CPU_BUFFERS_FOR_MMIO	BIT(2)
10 
11 #ifdef __ASSEMBLER__
12 .macro RESTORE_GUEST_SPEC_CTRL_BODY guest_spec_ctrl:req, label:req
13 	/*
14 	 * SPEC_CTRL handling: if the guest's SPEC_CTRL value differs from the
15 	 * host's, write the MSR.  This is kept out-of-line so that the common
16 	 * case does not have to jump.
17 	 *
18 	 * IMPORTANT: To avoid RSB underflow attacks and any other nastiness,
19 	 * there must not be any returns or indirect branches between this code
20 	 * and vmentry.
21 	 */
22 #ifdef CONFIG_X86_64
23 	mov \guest_spec_ctrl, %rdx
24 	cmp PER_CPU_VAR(x86_spec_ctrl_current), %rdx
25 	je \label
26 	movl %edx, %eax
27 	shr $32, %rdx
28 #else
29 	mov \guest_spec_ctrl, %eax
30 	mov PER_CPU_VAR(x86_spec_ctrl_current), %ecx
31 	xor %eax, %ecx
32 	mov 4 + \guest_spec_ctrl, %edx
33 	mov PER_CPU_VAR(x86_spec_ctrl_current + 4), %esi
34 	xor %edx, %esi
35 	or %esi, %ecx
36 	je \label
37 #endif
38 	mov $MSR_IA32_SPEC_CTRL, %ecx
39 	wrmsr
40 .endm
41 
42 .macro RESTORE_HOST_SPEC_CTRL_BODY guest_spec_ctrl:req, enter_flags:req, label:req
43 	/* Same for after vmexit.  */
44 	mov $MSR_IA32_SPEC_CTRL, %ecx
45 
46 	/*
47 	 * Load the value that the guest had written into MSR_IA32_SPEC_CTRL,
48 	 * if it was not intercepted during guest execution.
49 	 */
50 	testl $KVM_ENTER_SAVE_SPEC_CTRL, \enter_flags
51 	jz 998f
52 	rdmsr
53 	movl %eax, \guest_spec_ctrl
54 	movl %edx, 4 + \guest_spec_ctrl
55 998:
56 	/* Now restore the host value of the MSR if different from the guest's.  */
57 #ifdef CONFIG_X86_64
58 	mov PER_CPU_VAR(x86_spec_ctrl_current), %rdx
59 	cmp \guest_spec_ctrl, %rdx
60 	/*
61 	 * For legacy IBRS, the IBRS bit always needs to be written after
62 	 * transitioning from a less privileged predictor mode, regardless of
63 	 * whether the guest/host values differ.
64 	 */
65 	ALTERNATIVE __stringify(je \label), "", X86_FEATURE_KERNEL_IBRS
66 	movl %edx, %eax
67 	shr $32, %rdx
68 #else
69 	mov PER_CPU_VAR(x86_spec_ctrl_current), %eax
70 	mov \guest_spec_ctrl, %esi
71 	xor %eax, %esi
72 	mov PER_CPU_VAR(x86_spec_ctrl_current + 4), %edx
73 	mov 4 + \guest_spec_ctrl, %edi
74 	xor %edx, %edi
75 	or %edi, %esi
76 	ALTERNATIVE __stringify(je \label), "", X86_FEATURE_KERNEL_IBRS
77 #endif
78 	wrmsr
79 .endm
80 
81 #define WORD_SIZE (BITS_PER_LONG / 8)
82 
83 .macro LOAD_REGS src:req, regs_ofs:req, regs:vararg
84 .irp reg, \regs
85 	REG_NUM reg_num \reg
86 	mov (\regs_ofs + reg_num * WORD_SIZE)(\src), \reg
87 .endr
88 .endm
89 
90 .macro STORE_REGS dst:req, regs_ofs:req, regs:vararg
91 .irp reg, \regs
92 	REG_NUM reg_num \reg
93 	mov \reg, (\regs_ofs + reg_num * WORD_SIZE)(\dst)
94 .endr
95 .endm
96 
97 .macro POP_REGS dst:req, regs_ofs:req, regs:vararg
98 .irp reg, \regs
99 	REG_NUM reg_num \reg
100 	pop (\regs_ofs + reg_num * WORD_SIZE)(\dst)
101 .endr
102 .endm
103 
104 .macro CLEAR_REGS regs:vararg
105 .irp reg, \regs
106 	xorl \reg, \reg
107 .endr
108 .endm
109 
110 #endif /* __ASSEMBLER__ */
111 #endif /* __KVM_X86_VMENTER_H */
112