Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/x86/kvm/vmx/vmenter.S
26489 views
1
/* SPDX-License-Identifier: GPL-2.0 */
2
#include <linux/linkage.h>
3
#include <asm/asm.h>
4
#include <asm/bitsperlong.h>
5
#include <asm/kvm_vcpu_regs.h>
6
#include <asm/nospec-branch.h>
7
#include <asm/percpu.h>
8
#include <asm/segment.h>
9
#include "kvm-asm-offsets.h"
10
#include "run_flags.h"
11
12
#define WORD_SIZE (BITS_PER_LONG / 8)
13
14
#define VCPU_RAX __VCPU_REGS_RAX * WORD_SIZE
15
#define VCPU_RCX __VCPU_REGS_RCX * WORD_SIZE
16
#define VCPU_RDX __VCPU_REGS_RDX * WORD_SIZE
17
#define VCPU_RBX __VCPU_REGS_RBX * WORD_SIZE
18
/* Intentionally omit RSP as it's context switched by hardware */
19
#define VCPU_RBP __VCPU_REGS_RBP * WORD_SIZE
20
#define VCPU_RSI __VCPU_REGS_RSI * WORD_SIZE
21
#define VCPU_RDI __VCPU_REGS_RDI * WORD_SIZE
22
23
#ifdef CONFIG_X86_64
24
#define VCPU_R8 __VCPU_REGS_R8 * WORD_SIZE
25
#define VCPU_R9 __VCPU_REGS_R9 * WORD_SIZE
26
#define VCPU_R10 __VCPU_REGS_R10 * WORD_SIZE
27
#define VCPU_R11 __VCPU_REGS_R11 * WORD_SIZE
28
#define VCPU_R12 __VCPU_REGS_R12 * WORD_SIZE
29
#define VCPU_R13 __VCPU_REGS_R13 * WORD_SIZE
30
#define VCPU_R14 __VCPU_REGS_R14 * WORD_SIZE
31
#define VCPU_R15 __VCPU_REGS_R15 * WORD_SIZE
32
#endif
33
34
.macro VMX_DO_EVENT_IRQOFF call_insn call_target
35
/*
36
* Unconditionally create a stack frame, getting the correct RSP on the
37
* stack (for x86-64) would take two instructions anyways, and RBP can
38
* be used to restore RSP to make objtool happy (see below).
39
*/
40
push %_ASM_BP
41
mov %_ASM_SP, %_ASM_BP
42
43
#ifdef CONFIG_X86_64
44
/*
45
* Align RSP to a 16-byte boundary (to emulate CPU behavior) before
46
* creating the synthetic interrupt stack frame for the IRQ/NMI.
47
*/
48
and $-16, %rsp
49
push $__KERNEL_DS
50
push %rbp
51
#endif
52
pushf
53
push $__KERNEL_CS
54
\call_insn \call_target
55
56
/*
57
* "Restore" RSP from RBP, even though IRET has already unwound RSP to
58
* the correct value. objtool doesn't know the callee will IRET and,
59
* without the explicit restore, thinks the stack is getting walloped.
60
* Using an unwind hint is problematic due to x86-64's dynamic alignment.
61
*/
62
leave
63
RET
64
.endm
65
66
.section .noinstr.text, "ax"
67
68
/**
69
* __vmx_vcpu_run - Run a vCPU via a transition to VMX guest mode
70
* @vmx: struct vcpu_vmx *
71
* @regs: unsigned long * (to guest registers)
72
* @flags: VMX_RUN_VMRESUME: use VMRESUME instead of VMLAUNCH
73
* VMX_RUN_SAVE_SPEC_CTRL: save guest SPEC_CTRL into vmx->spec_ctrl
74
*
75
* Returns:
76
* 0 on VM-Exit, 1 on VM-Fail
77
*/
78
SYM_FUNC_START(__vmx_vcpu_run)
79
push %_ASM_BP
80
mov %_ASM_SP, %_ASM_BP
81
#ifdef CONFIG_X86_64
82
push %r15
83
push %r14
84
push %r13
85
push %r12
86
#else
87
push %edi
88
push %esi
89
#endif
90
push %_ASM_BX
91
92
/* Save @vmx for SPEC_CTRL handling */
93
push %_ASM_ARG1
94
95
/* Save @flags for SPEC_CTRL handling */
96
push %_ASM_ARG3
97
98
/*
99
* Save @regs, _ASM_ARG2 may be modified by vmx_update_host_rsp() and
100
* @regs is needed after VM-Exit to save the guest's register values.
101
*/
102
push %_ASM_ARG2
103
104
/* Copy @flags to EBX, _ASM_ARG3 is volatile. */
105
mov %_ASM_ARG3L, %ebx
106
107
lea (%_ASM_SP), %_ASM_ARG2
108
call vmx_update_host_rsp
109
110
ALTERNATIVE "jmp .Lspec_ctrl_done", "", X86_FEATURE_MSR_SPEC_CTRL
111
112
/*
113
* SPEC_CTRL handling: if the guest's SPEC_CTRL value differs from the
114
* host's, write the MSR.
115
*
116
* IMPORTANT: To avoid RSB underflow attacks and any other nastiness,
117
* there must not be any returns or indirect branches between this code
118
* and vmentry.
119
*/
120
mov 2*WORD_SIZE(%_ASM_SP), %_ASM_DI
121
movl VMX_spec_ctrl(%_ASM_DI), %edi
122
movl PER_CPU_VAR(x86_spec_ctrl_current), %esi
123
cmp %edi, %esi
124
je .Lspec_ctrl_done
125
mov $MSR_IA32_SPEC_CTRL, %ecx
126
xor %edx, %edx
127
mov %edi, %eax
128
wrmsr
129
130
.Lspec_ctrl_done:
131
132
/*
133
* Since vmentry is serializing on affected CPUs, there's no need for
134
* an LFENCE to stop speculation from skipping the wrmsr.
135
*/
136
137
/* Load @regs to RAX. */
138
mov (%_ASM_SP), %_ASM_AX
139
140
/* Check if vmlaunch or vmresume is needed */
141
bt $VMX_RUN_VMRESUME_SHIFT, %ebx
142
143
/* Load guest registers. Don't clobber flags. */
144
mov VCPU_RCX(%_ASM_AX), %_ASM_CX
145
mov VCPU_RDX(%_ASM_AX), %_ASM_DX
146
mov VCPU_RBX(%_ASM_AX), %_ASM_BX
147
mov VCPU_RBP(%_ASM_AX), %_ASM_BP
148
mov VCPU_RSI(%_ASM_AX), %_ASM_SI
149
mov VCPU_RDI(%_ASM_AX), %_ASM_DI
150
#ifdef CONFIG_X86_64
151
mov VCPU_R8 (%_ASM_AX), %r8
152
mov VCPU_R9 (%_ASM_AX), %r9
153
mov VCPU_R10(%_ASM_AX), %r10
154
mov VCPU_R11(%_ASM_AX), %r11
155
mov VCPU_R12(%_ASM_AX), %r12
156
mov VCPU_R13(%_ASM_AX), %r13
157
mov VCPU_R14(%_ASM_AX), %r14
158
mov VCPU_R15(%_ASM_AX), %r15
159
#endif
160
/* Load guest RAX. This kills the @regs pointer! */
161
mov VCPU_RAX(%_ASM_AX), %_ASM_AX
162
163
/* Clobbers EFLAGS.ZF */
164
CLEAR_CPU_BUFFERS
165
166
/* Check EFLAGS.CF from the VMX_RUN_VMRESUME bit test above. */
167
jnc .Lvmlaunch
168
169
/*
170
* After a successful VMRESUME/VMLAUNCH, control flow "magically"
171
* resumes below at 'vmx_vmexit' due to the VMCS HOST_RIP setting.
172
* So this isn't a typical function and objtool needs to be told to
173
* save the unwind state here and restore it below.
174
*/
175
UNWIND_HINT_SAVE
176
177
/*
178
* If VMRESUME/VMLAUNCH and corresponding vmexit succeed, execution resumes at
179
* the 'vmx_vmexit' label below.
180
*/
181
.Lvmresume:
182
vmresume
183
jmp .Lvmfail
184
185
.Lvmlaunch:
186
vmlaunch
187
jmp .Lvmfail
188
189
_ASM_EXTABLE(.Lvmresume, .Lfixup)
190
_ASM_EXTABLE(.Lvmlaunch, .Lfixup)
191
192
SYM_INNER_LABEL_ALIGN(vmx_vmexit, SYM_L_GLOBAL)
193
194
/* Restore unwind state from before the VMRESUME/VMLAUNCH. */
195
UNWIND_HINT_RESTORE
196
ENDBR
197
198
/* Temporarily save guest's RAX. */
199
push %_ASM_AX
200
201
/* Reload @regs to RAX. */
202
mov WORD_SIZE(%_ASM_SP), %_ASM_AX
203
204
/* Save all guest registers, including RAX from the stack */
205
pop VCPU_RAX(%_ASM_AX)
206
mov %_ASM_CX, VCPU_RCX(%_ASM_AX)
207
mov %_ASM_DX, VCPU_RDX(%_ASM_AX)
208
mov %_ASM_BX, VCPU_RBX(%_ASM_AX)
209
mov %_ASM_BP, VCPU_RBP(%_ASM_AX)
210
mov %_ASM_SI, VCPU_RSI(%_ASM_AX)
211
mov %_ASM_DI, VCPU_RDI(%_ASM_AX)
212
#ifdef CONFIG_X86_64
213
mov %r8, VCPU_R8 (%_ASM_AX)
214
mov %r9, VCPU_R9 (%_ASM_AX)
215
mov %r10, VCPU_R10(%_ASM_AX)
216
mov %r11, VCPU_R11(%_ASM_AX)
217
mov %r12, VCPU_R12(%_ASM_AX)
218
mov %r13, VCPU_R13(%_ASM_AX)
219
mov %r14, VCPU_R14(%_ASM_AX)
220
mov %r15, VCPU_R15(%_ASM_AX)
221
#endif
222
223
/* Clear return value to indicate VM-Exit (as opposed to VM-Fail). */
224
xor %ebx, %ebx
225
226
.Lclear_regs:
227
/* Discard @regs. The register is irrelevant, it just can't be RBX. */
228
pop %_ASM_AX
229
230
/*
231
* Clear all general purpose registers except RSP and RBX to prevent
232
* speculative use of the guest's values, even those that are reloaded
233
* via the stack. In theory, an L1 cache miss when restoring registers
234
* could lead to speculative execution with the guest's values.
235
* Zeroing XORs are dirt cheap, i.e. the extra paranoia is essentially
236
* free. RSP and RBX are exempt as RSP is restored by hardware during
237
* VM-Exit and RBX is explicitly loaded with 0 or 1 to hold the return
238
* value.
239
*/
240
xor %eax, %eax
241
xor %ecx, %ecx
242
xor %edx, %edx
243
xor %ebp, %ebp
244
xor %esi, %esi
245
xor %edi, %edi
246
#ifdef CONFIG_X86_64
247
xor %r8d, %r8d
248
xor %r9d, %r9d
249
xor %r10d, %r10d
250
xor %r11d, %r11d
251
xor %r12d, %r12d
252
xor %r13d, %r13d
253
xor %r14d, %r14d
254
xor %r15d, %r15d
255
#endif
256
257
/*
258
* IMPORTANT: RSB filling and SPEC_CTRL handling must be done before
259
* the first unbalanced RET after vmexit!
260
*
261
* For retpoline or IBRS, RSB filling is needed to prevent poisoned RSB
262
* entries and (in some cases) RSB underflow.
263
*
264
* eIBRS has its own protection against poisoned RSB, so it doesn't
265
* need the RSB filling sequence. But it does need to be enabled, and a
266
* single call to retire, before the first unbalanced RET.
267
*/
268
269
FILL_RETURN_BUFFER %_ASM_CX, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_VMEXIT,\
270
X86_FEATURE_RSB_VMEXIT_LITE
271
272
pop %_ASM_ARG2 /* @flags */
273
pop %_ASM_ARG1 /* @vmx */
274
275
call vmx_spec_ctrl_restore_host
276
277
CLEAR_BRANCH_HISTORY_VMEXIT
278
279
/* Put return value in AX */
280
mov %_ASM_BX, %_ASM_AX
281
282
pop %_ASM_BX
283
#ifdef CONFIG_X86_64
284
pop %r12
285
pop %r13
286
pop %r14
287
pop %r15
288
#else
289
pop %esi
290
pop %edi
291
#endif
292
pop %_ASM_BP
293
RET
294
295
.Lfixup:
296
cmpb $0, _ASM_RIP(kvm_rebooting)
297
jne .Lvmfail
298
ud2
299
.Lvmfail:
300
/* VM-Fail: set return value to 1 */
301
mov $1, %_ASM_BX
302
jmp .Lclear_regs
303
304
SYM_FUNC_END(__vmx_vcpu_run)
305
306
SYM_FUNC_START(vmx_do_nmi_irqoff)
307
VMX_DO_EVENT_IRQOFF call asm_exc_nmi_kvm_vmx
308
SYM_FUNC_END(vmx_do_nmi_irqoff)
309
310
#ifndef CONFIG_CC_HAS_ASM_GOTO_OUTPUT
311
312
/**
313
* vmread_error_trampoline - Trampoline from inline asm to vmread_error()
314
* @field: VMCS field encoding that failed
315
* @fault: %true if the VMREAD faulted, %false if it failed
316
*
317
* Save and restore volatile registers across a call to vmread_error(). Note,
318
* all parameters are passed on the stack.
319
*/
320
SYM_FUNC_START(vmread_error_trampoline)
321
push %_ASM_BP
322
mov %_ASM_SP, %_ASM_BP
323
324
push %_ASM_AX
325
push %_ASM_CX
326
push %_ASM_DX
327
#ifdef CONFIG_X86_64
328
push %rdi
329
push %rsi
330
push %r8
331
push %r9
332
push %r10
333
push %r11
334
#endif
335
336
/* Load @field and @fault to arg1 and arg2 respectively. */
337
mov 3*WORD_SIZE(%_ASM_BP), %_ASM_ARG2
338
mov 2*WORD_SIZE(%_ASM_BP), %_ASM_ARG1
339
340
call vmread_error_trampoline2
341
342
/* Zero out @fault, which will be popped into the result register. */
343
_ASM_MOV $0, 3*WORD_SIZE(%_ASM_BP)
344
345
#ifdef CONFIG_X86_64
346
pop %r11
347
pop %r10
348
pop %r9
349
pop %r8
350
pop %rsi
351
pop %rdi
352
#endif
353
pop %_ASM_DX
354
pop %_ASM_CX
355
pop %_ASM_AX
356
pop %_ASM_BP
357
358
RET
359
SYM_FUNC_END(vmread_error_trampoline)
360
#endif
361
362
.section .text, "ax"
363
364
SYM_FUNC_START(vmx_do_interrupt_irqoff)
365
VMX_DO_EVENT_IRQOFF CALL_NOSPEC _ASM_ARG1
366
SYM_FUNC_END(vmx_do_interrupt_irqoff)
367
368