3030
3131.section .noinstr.text, "ax"
3232
33- /**
34- * vmx_vmenter - VM-Enter the current loaded VMCS
35- *
36- * %RFLAGS.ZF: !VMCS.LAUNCHED, i.e. controls VMLAUNCH vs. VMRESUME
37- *
38- * Returns:
39- * %RFLAGS.CF is set on VM-Fail Invalid
40- * %RFLAGS.ZF is set on VM-Fail Valid
41- * %RFLAGS.{CF,ZF} are cleared on VM-Success, i.e. VM-Exit
42- *
43- * Note that VMRESUME/VMLAUNCH fall-through and return directly if
44- * they VM-Fail, whereas a successful VM-Enter + VM-Exit will jump
45- * to vmx_vmexit.
46- */
47- SYM_FUNC_START_LOCAL (vmx_vmenter)
48- /* EFLAGS.ZF is set if VMCS.LAUNCHED == 0 */
49- je 2f
50-
51- 1: vmresume
52- RET
53-
54- 2: vmlaunch
55- RET
56-
57- 3: cmpb $0 , kvm_rebooting
58- je 4f
59- RET
60- 4: ud2
61-
62- _ASM_EXTABLE(1b, 3b)
63- _ASM_EXTABLE(2b, 3b)
64-
65- SYM_FUNC_END(vmx_vmenter)
66-
67- /**
68- * vmx_vmexit - Handle a VMX VM-Exit
69- *
70- * Returns:
71- * %RFLAGS.{CF,ZF} are cleared on VM-Success, i.e. VM-Exit
72- *
73- * This is vmx_vmenter's partner in crime. On a VM-Exit, control will jump
74- * here after hardware loads the host's state, i.e. this is the destination
75- * referred to by VMCS.HOST_RIP.
76- */
77- SYM_FUNC_START(vmx_vmexit)
78- #ifdef CONFIG_RETPOLINE
79- ALTERNATIVE "jmp .Lvmexit_skip_rsb" , "", X86_FEATURE_RETPOLINE
80- /* Preserve guest's RAX, it's used to stuff the RSB. */
81- push %_ASM_AX
82-
83- /* IMPORTANT: Stuff the RSB immediately after VM-Exit, before RET! */
84- FILL_RETURN_BUFFER %_ASM_AX, RSB_CLEAR_LOOPS, X86_FEATURE_RETPOLINE
85-
86- /* Clear RFLAGS.CF and RFLAGS.ZF to preserve VM-Exit, i.e. !VM-Fail. */
87- or $1 , %_ASM_AX
88-
89- pop %_ASM_AX
90- .Lvmexit_skip_rsb:
91- #endif
92- RET
93- SYM_FUNC_END(vmx_vmexit)
94-
9533/**
9634 * __vmx_vcpu_run - Run a vCPU via a transition to VMX guest mode
9735 * @vmx: struct vcpu_vmx * (forwarded to vmx_update_host_rsp)
@@ -124,8 +62,7 @@ SYM_FUNC_START(__vmx_vcpu_run)
12462 /* Copy @launched to BL, _ASM_ARG3 is volatile. */
12563 mov %_ASM_ARG3B, %bl
12664
127- /* Adjust RSP to account for the CALL to vmx_vmenter(). */
128- lea -WORD_SIZE(%_ASM_SP), %_ASM_ARG2
65+ lea (%_ASM_SP), %_ASM_ARG2
12966 call vmx_update_host_rsp
13067
13168 /* Load @regs to RAX. */
@@ -154,11 +91,37 @@ SYM_FUNC_START(__vmx_vcpu_run)
15491 /* Load guest RAX. This kills the @regs pointer! */
15592 mov VCPU_RAX(%_ASM_AX), %_ASM_AX
15693
157- /* Enter guest mode */
158- call vmx_vmenter
94+ /* Check EFLAGS.ZF from 'testb' above */
95+ je .Lvmlaunch
96+
97+ /*
98+ * After a successful VMRESUME/VMLAUNCH, control flow "magically"
99+ * resumes below at 'vmx_vmexit' due to the VMCS HOST_RIP setting.
100+ * So this isn't a typical function and objtool needs to be told to
101+ * save the unwind state here and restore it below.
102+ */
103+ UNWIND_HINT_SAVE
104+
105+ /*
106+ * If VMRESUME/VMLAUNCH and corresponding vmexit succeed, execution resumes at
107+ * the 'vmx_vmexit' label below.
108+ */
109+ .Lvmresume:
110+ vmresume
111+ jmp .Lvmfail
112+
113+ .Lvmlaunch:
114+ vmlaunch
115+ jmp .Lvmfail
116+
117+ _ASM_EXTABLE(.Lvmresume, .Lfixup)
118+ _ASM_EXTABLE(.Lvmlaunch, .Lfixup)
159119
160- /* Jump on VM-Fail. */
161- jbe 2f
120+ SYM_INNER_LABEL(vmx_vmexit, SYM_L_GLOBAL)
121+
122+ /* Restore unwind state from before the VMRESUME/VMLAUNCH. */
123+ UNWIND_HINT_RESTORE
124+ ENDBR
162125
163126 /* Temporarily save guest's RAX. */
164127 push %_ASM_AX
@@ -185,9 +148,13 @@ SYM_FUNC_START(__vmx_vcpu_run)
185148 mov %r15 , VCPU_R15(%_ASM_AX)
186149#endif
187150
151+ /* IMPORTANT: RSB must be stuffed before the first return. */
152+ FILL_RETURN_BUFFER %_ASM_BX, RSB_CLEAR_LOOPS, X86_FEATURE_RETPOLINE
153+
188154 /* Clear RAX to indicate VM-Exit (as opposed to VM-Fail). */
189155 xor %eax , %eax
190156
157+ .Lclear_regs:
191158 /*
192159 * Clear all general purpose registers except RSP and RAX to prevent
193160 * speculative use of the guest's values, even those that are reloaded
@@ -197,7 +164,7 @@ SYM_FUNC_START(__vmx_vcpu_run)
197164 * free. RSP and RAX are exempt as RSP is restored by hardware during
198165 * VM-Exit and RAX is explicitly loaded with 0 or 1 to return VM-Fail.
199166 */
200- 1: xor %ecx , %ecx
167+ xor %ecx , %ecx
201168 xor %edx , %edx
202169 xor %ebx , %ebx
203170 xor %ebp , %ebp
@@ -216,8 +183,8 @@ SYM_FUNC_START(__vmx_vcpu_run)
216183
217184 /* "POP" @regs. */
218185 add $WORD_SIZE, %_ASM_SP
219- pop %_ASM_BX
220186
187+ pop %_ASM_BX
221188#ifdef CONFIG_X86_64
222189 pop %r12
223190 pop %r13
@@ -230,9 +197,15 @@ SYM_FUNC_START(__vmx_vcpu_run)
230197 pop %_ASM_BP
231198 RET
232199
233- /* VM-Fail. Out-of-line to avoid a taken Jcc after VM-Exit. */
234- 2: mov $1 , %eax
235- jmp 1b
200+ .Lfixup:
201+ cmpb $0 , kvm_rebooting
202+ jne .Lvmfail
203+ ud2
204+ .Lvmfail:
205+ /* VM-Fail: set return value to 1 */
206+ mov $1 , %eax
207+ jmp .Lclear_regs
208+
236209SYM_FUNC_END(__vmx_vcpu_run)
237210
238211
0 commit comments