blob: 011ec649f38869328c48c079cfe47af15eeadccc [file] [log] [blame]
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Asm versions of Xen pv-ops, suitable for direct use.
4 *
5 * We only bother with direct forms (ie, vcpu in percpu data) of the
6 * operations here; the indirect forms are better handled in C.
7 */
8
Olivier Deprez157378f2022-04-04 15:47:50 +02009#include <asm/errno.h>
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000010#include <asm/asm-offsets.h>
11#include <asm/percpu.h>
12#include <asm/processor-flags.h>
Olivier Deprez157378f2022-04-04 15:47:50 +020013#include <asm/segment.h>
14#include <asm/thread_info.h>
David Brazdil0f672f62019-12-10 10:32:29 +000015#include <asm/asm.h>
Olivier Deprez157378f2022-04-04 15:47:50 +020016#include <asm/frame.h>
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000017
Olivier Deprez157378f2022-04-04 15:47:50 +020018#include <xen/interface/xen.h>
19
20#include <linux/init.h>
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000021#include <linux/linkage.h>
Olivier Deprez157378f2022-04-04 15:47:50 +020022#include <../entry/calling.h>
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000023
24/*
25 * Enable events. This clears the event mask and tests the pending
26 * event status with one and operation. If there are pending events,
27 * then enter the hypervisor to get them handled.
28 */
Olivier Deprez157378f2022-04-04 15:47:50 +020029SYM_FUNC_START(xen_irq_enable_direct)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000030 FRAME_BEGIN
31 /* Unmask events */
32 movb $0, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask
33
34 /*
35 * Preempt here doesn't matter because that will deal with any
36 * pending interrupts. The pending check may end up being run
37 * on the wrong CPU, but that doesn't hurt.
38 */
39
40 /* Test for pending */
41 testb $0xff, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_pending
42 jz 1f
43
44 call check_events
451:
46 FRAME_END
47 ret
Olivier Deprez157378f2022-04-04 15:47:50 +020048SYM_FUNC_END(xen_irq_enable_direct)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000049
50
51/*
52 * Disabling events is simply a matter of making the event mask
53 * non-zero.
54 */
Olivier Deprez157378f2022-04-04 15:47:50 +020055SYM_FUNC_START(xen_irq_disable_direct)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000056 movb $1, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask
57 ret
Olivier Deprez157378f2022-04-04 15:47:50 +020058SYM_FUNC_END(xen_irq_disable_direct)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000059
60/*
61 * (xen_)save_fl is used to get the current interrupt enable status.
62 * Callers expect the status to be in X86_EFLAGS_IF, and other bits
63 * may be set in the return value. We take advantage of this by
64 * making sure that X86_EFLAGS_IF has the right value (and other bits
65 * in that byte are 0), but other bits in the return value are
66 * undefined. We need to toggle the state of the bit, because Xen and
67 * x86 use opposite senses (mask vs enable).
68 */
Olivier Deprez157378f2022-04-04 15:47:50 +020069SYM_FUNC_START(xen_save_fl_direct)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000070 testb $0xff, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask
71 setz %ah
72 addb %ah, %ah
73 ret
Olivier Deprez157378f2022-04-04 15:47:50 +020074SYM_FUNC_END(xen_save_fl_direct)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000075
76
77/*
78 * In principle the caller should be passing us a value return from
79 * xen_save_fl_direct, but for robustness sake we test only the
80 * X86_EFLAGS_IF flag rather than the whole byte. After setting the
81 * interrupt mask state, it checks for unmasked pending events and
82 * enters the hypervisor to get them delivered if so.
83 */
Olivier Deprez157378f2022-04-04 15:47:50 +020084SYM_FUNC_START(xen_restore_fl_direct)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000085 FRAME_BEGIN
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000086 testw $X86_EFLAGS_IF, %di
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000087 setz PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask
88 /*
89 * Preempt here doesn't matter because that will deal with any
90 * pending interrupts. The pending check may end up being run
91 * on the wrong CPU, but that doesn't hurt.
92 */
93
94 /* check for unmasked and pending */
95 cmpw $0x0001, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_pending
96 jnz 1f
97 call check_events
981:
99 FRAME_END
100 ret
Olivier Deprez157378f2022-04-04 15:47:50 +0200101SYM_FUNC_END(xen_restore_fl_direct)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000102
103
104/*
105 * Force an event check by making a hypercall, but preserve regs
106 * before making the call.
107 */
Olivier Deprez157378f2022-04-04 15:47:50 +0200108SYM_FUNC_START(check_events)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000109 FRAME_BEGIN
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000110 push %rax
111 push %rcx
112 push %rdx
113 push %rsi
114 push %rdi
115 push %r8
116 push %r9
117 push %r10
118 push %r11
119 call xen_force_evtchn_callback
120 pop %r11
121 pop %r10
122 pop %r9
123 pop %r8
124 pop %rdi
125 pop %rsi
126 pop %rdx
127 pop %rcx
128 pop %rax
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000129 FRAME_END
130 ret
Olivier Deprez157378f2022-04-04 15:47:50 +0200131SYM_FUNC_END(check_events)
David Brazdil0f672f62019-12-10 10:32:29 +0000132
Olivier Deprez157378f2022-04-04 15:47:50 +0200133SYM_FUNC_START(xen_read_cr2)
David Brazdil0f672f62019-12-10 10:32:29 +0000134 FRAME_BEGIN
135 _ASM_MOV PER_CPU_VAR(xen_vcpu), %_ASM_AX
136 _ASM_MOV XEN_vcpu_info_arch_cr2(%_ASM_AX), %_ASM_AX
137 FRAME_END
138 ret
Olivier Deprez157378f2022-04-04 15:47:50 +0200139SYM_FUNC_END(xen_read_cr2);
David Brazdil0f672f62019-12-10 10:32:29 +0000140
Olivier Deprez157378f2022-04-04 15:47:50 +0200141SYM_FUNC_START(xen_read_cr2_direct)
David Brazdil0f672f62019-12-10 10:32:29 +0000142 FRAME_BEGIN
143 _ASM_MOV PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_arch_cr2, %_ASM_AX
144 FRAME_END
145 ret
Olivier Deprez157378f2022-04-04 15:47:50 +0200146SYM_FUNC_END(xen_read_cr2_direct);
147
148.macro xen_pv_trap name
149SYM_CODE_START(xen_\name)
150 pop %rcx
151 pop %r11
152 jmp \name
153SYM_CODE_END(xen_\name)
154_ASM_NOKPROBE(xen_\name)
155.endm
156
157xen_pv_trap asm_exc_divide_error
158xen_pv_trap asm_xenpv_exc_debug
159xen_pv_trap asm_exc_int3
160xen_pv_trap asm_xenpv_exc_nmi
161xen_pv_trap asm_exc_overflow
162xen_pv_trap asm_exc_bounds
163xen_pv_trap asm_exc_invalid_op
164xen_pv_trap asm_exc_device_not_available
165xen_pv_trap asm_exc_double_fault
166xen_pv_trap asm_exc_coproc_segment_overrun
167xen_pv_trap asm_exc_invalid_tss
168xen_pv_trap asm_exc_segment_not_present
169xen_pv_trap asm_exc_stack_segment
170xen_pv_trap asm_exc_general_protection
171xen_pv_trap asm_exc_page_fault
172xen_pv_trap asm_exc_spurious_interrupt_bug
173xen_pv_trap asm_exc_coprocessor_error
174xen_pv_trap asm_exc_alignment_check
175#ifdef CONFIG_X86_MCE
176xen_pv_trap asm_exc_machine_check
177#endif /* CONFIG_X86_MCE */
178xen_pv_trap asm_exc_simd_coprocessor_error
179#ifdef CONFIG_IA32_EMULATION
180xen_pv_trap entry_INT80_compat
181#endif
182xen_pv_trap asm_exc_xen_unknown_trap
183xen_pv_trap asm_exc_xen_hypervisor_callback
184
185 __INIT
186SYM_CODE_START(xen_early_idt_handler_array)
187 i = 0
188 .rept NUM_EXCEPTION_VECTORS
189 pop %rcx
190 pop %r11
191 jmp early_idt_handler_array + i*EARLY_IDT_HANDLER_SIZE
192 i = i + 1
193 .fill xen_early_idt_handler_array + i*XEN_EARLY_IDT_HANDLER_SIZE - ., 1, 0xcc
194 .endr
195SYM_CODE_END(xen_early_idt_handler_array)
196 __FINIT
197
198hypercall_iret = hypercall_page + __HYPERVISOR_iret * 32
199/*
200 * Xen64 iret frame:
201 *
202 * ss
203 * rsp
204 * rflags
205 * cs
206 * rip <-- standard iret frame
207 *
208 * flags
209 *
210 * rcx }
211 * r11 }<-- pushed by hypercall page
212 * rsp->rax }
213 */
214SYM_CODE_START(xen_iret)
215 pushq $0
216 jmp hypercall_iret
217SYM_CODE_END(xen_iret)
218
219SYM_CODE_START(xen_sysret64)
220 /*
221 * We're already on the usermode stack at this point, but
222 * still with the kernel gs, so we can easily switch back.
223 *
224 * tss.sp2 is scratch space.
225 */
226 movq %rsp, PER_CPU_VAR(cpu_tss_rw + TSS_sp2)
227 movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
228
229 pushq $__USER_DS
230 pushq PER_CPU_VAR(cpu_tss_rw + TSS_sp2)
231 pushq %r11
232 pushq $__USER_CS
233 pushq %rcx
234
235 pushq $VGCF_in_syscall
236 jmp hypercall_iret
237SYM_CODE_END(xen_sysret64)
238
239/*
240 * XEN pv doesn't use trampoline stack, PER_CPU_VAR(cpu_tss_rw + TSS_sp0) is
241 * also the kernel stack. Reusing swapgs_restore_regs_and_return_to_usermode()
242 * in XEN pv would cause %rsp to move up to the top of the kernel stack and
243 * leave the IRET frame below %rsp, which is dangerous to be corrupted if #NMI
244 * interrupts. And swapgs_restore_regs_and_return_to_usermode() pushing the IRET
245 * frame at the same address is useless.
246 */
247SYM_CODE_START(xenpv_restore_regs_and_return_to_usermode)
248 UNWIND_HINT_REGS
249 POP_REGS
250
251 /* stackleak_erase() can work safely on the kernel stack. */
252 STACKLEAK_ERASE_NOCLOBBER
253
254 addq $8, %rsp /* skip regs->orig_ax */
255 jmp xen_iret
256SYM_CODE_END(xenpv_restore_regs_and_return_to_usermode)
257
258/*
259 * Xen handles syscall callbacks much like ordinary exceptions, which
260 * means we have:
261 * - kernel gs
262 * - kernel rsp
263 * - an iret-like stack frame on the stack (including rcx and r11):
264 * ss
265 * rsp
266 * rflags
267 * cs
268 * rip
269 * r11
270 * rsp->rcx
271 */
272
273/* Normal 64-bit system call target */
274SYM_FUNC_START(xen_syscall_target)
275 popq %rcx
276 popq %r11
277
278 /*
279 * Neither Xen nor the kernel really knows what the old SS and
280 * CS were. The kernel expects __USER_DS and __USER_CS, so
281 * report those values even though Xen will guess its own values.
282 */
283 movq $__USER_DS, 4*8(%rsp)
284 movq $__USER_CS, 1*8(%rsp)
285
286 jmp entry_SYSCALL_64_after_hwframe
287SYM_FUNC_END(xen_syscall_target)
288
289#ifdef CONFIG_IA32_EMULATION
290
291/* 32-bit compat syscall target */
292SYM_FUNC_START(xen_syscall32_target)
293 popq %rcx
294 popq %r11
295
296 /*
297 * Neither Xen nor the kernel really knows what the old SS and
298 * CS were. The kernel expects __USER32_DS and __USER32_CS, so
299 * report those values even though Xen will guess its own values.
300 */
301 movq $__USER32_DS, 4*8(%rsp)
302 movq $__USER32_CS, 1*8(%rsp)
303
304 jmp entry_SYSCALL_compat_after_hwframe
305SYM_FUNC_END(xen_syscall32_target)
306
307/* 32-bit compat sysenter target */
308SYM_FUNC_START(xen_sysenter_target)
309 /*
310 * NB: Xen is polite and clears TF from EFLAGS for us. This means
311 * that we don't need to guard against single step exceptions here.
312 */
313 popq %rcx
314 popq %r11
315
316 /*
317 * Neither Xen nor the kernel really knows what the old SS and
318 * CS were. The kernel expects __USER32_DS and __USER32_CS, so
319 * report those values even though Xen will guess its own values.
320 */
321 movq $__USER32_DS, 4*8(%rsp)
322 movq $__USER32_CS, 1*8(%rsp)
323
324 jmp entry_SYSENTER_compat_after_hwframe
325SYM_FUNC_END(xen_sysenter_target)
326
327#else /* !CONFIG_IA32_EMULATION */
328
329SYM_FUNC_START_ALIAS(xen_syscall32_target)
330SYM_FUNC_START(xen_sysenter_target)
331 lea 16(%rsp), %rsp /* strip %rcx, %r11 */
332 mov $-ENOSYS, %rax
333 pushq $0
334 jmp hypercall_iret
335SYM_FUNC_END(xen_sysenter_target)
336SYM_FUNC_END_ALIAS(xen_syscall32_target)
337
338#endif /* CONFIG_IA32_EMULATION */