xref: /openbmc/linux/arch/x86/xen/xen-asm.S (revision aad29a73199b7fbccfbabea3f1ee627ad1924f52)
1b2441318SGreg Kroah-Hartman/* SPDX-License-Identifier: GPL-2.0 */
25393744bSJeremy Fitzhardinge/*
3edcb5cf8SJuergen Gross * Asm versions of Xen pv-ops, suitable for direct use.
4130ace11STejun Heo *
5130ace11STejun Heo * We only bother with direct forms (ie, vcpu in percpu data) of the
6edcb5cf8SJuergen Gross * operations here; the indirect forms are better handled in C.
75393744bSJeremy Fitzhardinge */
85393744bSJeremy Fitzhardinge
956415c4cSJuergen Gross#include <asm/errno.h>
105393744bSJeremy Fitzhardinge#include <asm/asm-offsets.h>
115393744bSJeremy Fitzhardinge#include <asm/percpu.h>
125393744bSJeremy Fitzhardinge#include <asm/processor-flags.h>
1356415c4cSJuergen Gross#include <asm/segment.h>
1456415c4cSJuergen Gross#include <asm/thread_info.h>
1555aedddbSPeter Zijlstra#include <asm/asm.h>
1656415c4cSJuergen Gross#include <asm/frame.h>
17cde07a4eSJosh Poimboeuf#include <asm/unwind_hints.h>
185393744bSJeremy Fitzhardinge
1956415c4cSJuergen Gross#include <xen/interface/xen.h>
2056415c4cSJuergen Gross
2156415c4cSJuergen Gross#include <linux/init.h>
22edcb5cf8SJuergen Gross#include <linux/linkage.h>
2331f29270SJuergen Gross#include <linux/objtool.h>
245c8f6a2eSLai Jiangshan#include <../entry/calling.h>
255393744bSJeremy Fitzhardinge
2609c41307SPeter Zijlstra.pushsection .noinstr.text, "ax"
275393744bSJeremy Fitzhardinge/*
2831f29270SJuergen Gross * PV hypercall interface to the hypervisor.
2931f29270SJuergen Gross *
3031f29270SJuergen Gross * Called via inline asm(), so better preserve %rcx and %r11.
3131f29270SJuergen Gross *
3231f29270SJuergen Gross * Input:
3331f29270SJuergen Gross *	%eax: hypercall number
3431f29270SJuergen Gross *	%rdi, %rsi, %rdx, %r10, %r8: args 1..5 for the hypercall
3531f29270SJuergen Gross * Output: %rax
3631f29270SJuergen Gross */
3731f29270SJuergen GrossSYM_FUNC_START(xen_hypercall_pv)
3831f29270SJuergen Gross	ANNOTATE_NOENDBR
3931f29270SJuergen Gross	push %rcx
4031f29270SJuergen Gross	push %r11
4131f29270SJuergen Gross	UNWIND_HINT_SAVE
4231f29270SJuergen Gross	syscall
4331f29270SJuergen Gross	UNWIND_HINT_RESTORE
4431f29270SJuergen Gross	pop %r11
4531f29270SJuergen Gross	pop %rcx
4631f29270SJuergen Gross	RET
4731f29270SJuergen GrossSYM_FUNC_END(xen_hypercall_pv)
4831f29270SJuergen Gross
4931f29270SJuergen Gross/*
50130ace11STejun Heo * Disabling events is simply a matter of making the event mask
51130ace11STejun Heo * non-zero.
525393744bSJeremy Fitzhardinge */
536dcc5627SJiri SlabySYM_FUNC_START(xen_irq_disable_direct)
545393744bSJeremy Fitzhardinge	movb $1, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask
55f94909ceSPeter Zijlstra	RET
566dcc5627SJiri SlabySYM_FUNC_END(xen_irq_disable_direct)
575393744bSJeremy Fitzhardinge
585393744bSJeremy Fitzhardinge/*
59130ace11STejun Heo * Force an event check by making a hypercall, but preserve regs
60130ace11STejun Heo * before making the call.
615393744bSJeremy Fitzhardinge */
626dcc5627SJiri SlabySYM_FUNC_START(check_events)
638be0eb7eSJosh Poimboeuf	FRAME_BEGIN
645393744bSJeremy Fitzhardinge	push %rax
655393744bSJeremy Fitzhardinge	push %rcx
665393744bSJeremy Fitzhardinge	push %rdx
675393744bSJeremy Fitzhardinge	push %rsi
685393744bSJeremy Fitzhardinge	push %rdi
695393744bSJeremy Fitzhardinge	push %r8
705393744bSJeremy Fitzhardinge	push %r9
715393744bSJeremy Fitzhardinge	push %r10
725393744bSJeremy Fitzhardinge	push %r11
735393744bSJeremy Fitzhardinge	call xen_force_evtchn_callback
745393744bSJeremy Fitzhardinge	pop %r11
755393744bSJeremy Fitzhardinge	pop %r10
765393744bSJeremy Fitzhardinge	pop %r9
775393744bSJeremy Fitzhardinge	pop %r8
785393744bSJeremy Fitzhardinge	pop %rdi
795393744bSJeremy Fitzhardinge	pop %rsi
805393744bSJeremy Fitzhardinge	pop %rdx
815393744bSJeremy Fitzhardinge	pop %rcx
825393744bSJeremy Fitzhardinge	pop %rax
838be0eb7eSJosh Poimboeuf	FRAME_END
84f94909ceSPeter Zijlstra	RET
856dcc5627SJiri SlabySYM_FUNC_END(check_events)
8655aedddbSPeter Zijlstra
87d7bfc7d5SPeter Zijlstra/*
88d7bfc7d5SPeter Zijlstra * Enable events.  This clears the event mask and tests the pending
89d7bfc7d5SPeter Zijlstra * event status with one and operation.  If there are pending events,
90d7bfc7d5SPeter Zijlstra * then enter the hypervisor to get them handled.
91d7bfc7d5SPeter Zijlstra */
92d7bfc7d5SPeter ZijlstraSYM_FUNC_START(xen_irq_enable_direct)
93d7bfc7d5SPeter Zijlstra	FRAME_BEGIN
94d7bfc7d5SPeter Zijlstra	/* Unmask events */
95d7bfc7d5SPeter Zijlstra	movb $0, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask
96d7bfc7d5SPeter Zijlstra
97d7bfc7d5SPeter Zijlstra	/*
98d7bfc7d5SPeter Zijlstra	 * Preempt here doesn't matter because that will deal with any
99d7bfc7d5SPeter Zijlstra	 * pending interrupts.  The pending check may end up being run
100d7bfc7d5SPeter Zijlstra	 * on the wrong CPU, but that doesn't hurt.
101d7bfc7d5SPeter Zijlstra	 */
102d7bfc7d5SPeter Zijlstra
103d7bfc7d5SPeter Zijlstra	/* Test for pending */
104d7bfc7d5SPeter Zijlstra	testb $0xff, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_pending
105d7bfc7d5SPeter Zijlstra	jz 1f
106d7bfc7d5SPeter Zijlstra
107d7bfc7d5SPeter Zijlstra	call check_events
108d7bfc7d5SPeter Zijlstra1:
109d7bfc7d5SPeter Zijlstra	FRAME_END
110f94909ceSPeter Zijlstra	RET
111d7bfc7d5SPeter ZijlstraSYM_FUNC_END(xen_irq_enable_direct)
112d7bfc7d5SPeter Zijlstra
11320125c87SPeter Zijlstra/*
11420125c87SPeter Zijlstra * (xen_)save_fl is used to get the current interrupt enable status.
11520125c87SPeter Zijlstra * Callers expect the status to be in X86_EFLAGS_IF, and other bits
11620125c87SPeter Zijlstra * may be set in the return value.  We take advantage of this by
11720125c87SPeter Zijlstra * making sure that X86_EFLAGS_IF has the right value (and other bits
11820125c87SPeter Zijlstra * in that byte are 0), but other bits in the return value are
11920125c87SPeter Zijlstra * undefined.  We need to toggle the state of the bit, because Xen and
12020125c87SPeter Zijlstra * x86 use opposite senses (mask vs enable).
12120125c87SPeter Zijlstra */
12220125c87SPeter ZijlstraSYM_FUNC_START(xen_save_fl_direct)
12320125c87SPeter Zijlstra	testb $0xff, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask
12420125c87SPeter Zijlstra	setz %ah
12520125c87SPeter Zijlstra	addb %ah, %ah
126f94909ceSPeter Zijlstra	RET
12720125c87SPeter ZijlstraSYM_FUNC_END(xen_save_fl_direct)
12820125c87SPeter Zijlstra
1296dcc5627SJiri SlabySYM_FUNC_START(xen_read_cr2)
13055aedddbSPeter Zijlstra	FRAME_BEGIN
13155aedddbSPeter Zijlstra	_ASM_MOV PER_CPU_VAR(xen_vcpu), %_ASM_AX
13255aedddbSPeter Zijlstra	_ASM_MOV XEN_vcpu_info_arch_cr2(%_ASM_AX), %_ASM_AX
13355aedddbSPeter Zijlstra	FRAME_END
134f94909ceSPeter Zijlstra	RET
1356dcc5627SJiri SlabySYM_FUNC_END(xen_read_cr2);
13655aedddbSPeter Zijlstra
1376dcc5627SJiri SlabySYM_FUNC_START(xen_read_cr2_direct)
13855aedddbSPeter Zijlstra	FRAME_BEGIN
13955aedddbSPeter Zijlstra	_ASM_MOV PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_arch_cr2, %_ASM_AX
14055aedddbSPeter Zijlstra	FRAME_END
141f94909ceSPeter Zijlstra	RET
1426dcc5627SJiri SlabySYM_FUNC_END(xen_read_cr2_direct);
1430a53c9acSPeter Zijlstra.popsection
14456415c4cSJuergen Gross
14556415c4cSJuergen Gross.macro xen_pv_trap name
14656415c4cSJuergen GrossSYM_CODE_START(xen_\name)
147a09a6e23SPeter Zijlstra	UNWIND_HINT_ENTRY
1485b2fc515SPeter Zijlstra	ENDBR
14956415c4cSJuergen Gross	pop %rcx
15056415c4cSJuergen Gross	pop %r11
15156415c4cSJuergen Gross	jmp  \name
15256415c4cSJuergen GrossSYM_CODE_END(xen_\name)
15356415c4cSJuergen Gross_ASM_NOKPROBE(xen_\name)
15456415c4cSJuergen Gross.endm
15556415c4cSJuergen Gross
15656415c4cSJuergen Grossxen_pv_trap asm_exc_divide_error
15756415c4cSJuergen Grossxen_pv_trap asm_xenpv_exc_debug
15856415c4cSJuergen Grossxen_pv_trap asm_exc_int3
15956415c4cSJuergen Grossxen_pv_trap asm_xenpv_exc_nmi
16056415c4cSJuergen Grossxen_pv_trap asm_exc_overflow
16156415c4cSJuergen Grossxen_pv_trap asm_exc_bounds
16256415c4cSJuergen Grossxen_pv_trap asm_exc_invalid_op
16356415c4cSJuergen Grossxen_pv_trap asm_exc_device_not_available
1645b4c6d65SJuergen Grossxen_pv_trap asm_xenpv_exc_double_fault
16556415c4cSJuergen Grossxen_pv_trap asm_exc_coproc_segment_overrun
16656415c4cSJuergen Grossxen_pv_trap asm_exc_invalid_tss
16756415c4cSJuergen Grossxen_pv_trap asm_exc_segment_not_present
16856415c4cSJuergen Grossxen_pv_trap asm_exc_stack_segment
16956415c4cSJuergen Grossxen_pv_trap asm_exc_general_protection
17056415c4cSJuergen Grossxen_pv_trap asm_exc_page_fault
17156415c4cSJuergen Grossxen_pv_trap asm_exc_spurious_interrupt_bug
17256415c4cSJuergen Grossxen_pv_trap asm_exc_coprocessor_error
17356415c4cSJuergen Grossxen_pv_trap asm_exc_alignment_check
174a5f6c2acSRick Edgecombe#ifdef CONFIG_X86_CET
1755b2fc515SPeter Zijlstraxen_pv_trap asm_exc_control_protection
1765b2fc515SPeter Zijlstra#endif
17756415c4cSJuergen Gross#ifdef CONFIG_X86_MCE
178c3d7fa66SJuergen Grossxen_pv_trap asm_xenpv_exc_machine_check
17956415c4cSJuergen Gross#endif /* CONFIG_X86_MCE */
18056415c4cSJuergen Grossxen_pv_trap asm_exc_simd_coprocessor_error
18156415c4cSJuergen Gross#ifdef CONFIG_IA32_EMULATION
1824591766fSThomas Gleixnerxen_pv_trap asm_int80_emulation
18356415c4cSJuergen Gross#endif
1842e924936SJuergen Grossxen_pv_trap asm_exc_xen_unknown_trap
18556415c4cSJuergen Grossxen_pv_trap asm_exc_xen_hypervisor_callback
18656415c4cSJuergen Gross
18756415c4cSJuergen Gross	__INIT
18856415c4cSJuergen GrossSYM_CODE_START(xen_early_idt_handler_array)
18956415c4cSJuergen Gross	i = 0
19056415c4cSJuergen Gross	.rept NUM_EXCEPTION_VECTORS
191fb799447SJosh Poimboeuf	UNWIND_HINT_UNDEFINED
1925b2fc515SPeter Zijlstra	ENDBR
19356415c4cSJuergen Gross	pop %rcx
19456415c4cSJuergen Gross	pop %r11
19556415c4cSJuergen Gross	jmp early_idt_handler_array + i*EARLY_IDT_HANDLER_SIZE
19656415c4cSJuergen Gross	i = i + 1
19756415c4cSJuergen Gross	.fill xen_early_idt_handler_array + i*XEN_EARLY_IDT_HANDLER_SIZE - ., 1, 0xcc
19856415c4cSJuergen Gross	.endr
19956415c4cSJuergen GrossSYM_CODE_END(xen_early_idt_handler_array)
20056415c4cSJuergen Gross	__FINIT
20156415c4cSJuergen Gross
20256415c4cSJuergen Gross/*
20356415c4cSJuergen Gross * Xen64 iret frame:
20456415c4cSJuergen Gross *
20556415c4cSJuergen Gross *	ss
20656415c4cSJuergen Gross *	rsp
20756415c4cSJuergen Gross *	rflags
20856415c4cSJuergen Gross *	cs
20956415c4cSJuergen Gross *	rip		<-- standard iret frame
21056415c4cSJuergen Gross *
21182c211eaSJuergen Gross *	flags		<-- xen_iret must push from here on
21256415c4cSJuergen Gross *
21382c211eaSJuergen Gross *	rcx
21482c211eaSJuergen Gross *	r11
21582c211eaSJuergen Gross * rsp->rax
21656415c4cSJuergen Gross */
21782c211eaSJuergen Gross.macro xen_hypercall_iret
21882c211eaSJuergen Gross	pushq $0	/* Flags */
21982c211eaSJuergen Gross	push %rcx
22082c211eaSJuergen Gross	push %r11
22182c211eaSJuergen Gross	push %rax
22282c211eaSJuergen Gross	mov  $__HYPERVISOR_iret, %eax
22382c211eaSJuergen Gross	syscall		/* Do the IRET. */
224*7d082fb2SJuergen Gross#ifdef CONFIG_SLS
22582c211eaSJuergen Gross	int3
22682c211eaSJuergen Gross#endif
22782c211eaSJuergen Gross.endm
22882c211eaSJuergen Gross
22956415c4cSJuergen GrossSYM_CODE_START(xen_iret)
230fb799447SJosh Poimboeuf	UNWIND_HINT_UNDEFINED
2318b87d8ceSPeter Zijlstra	ANNOTATE_NOENDBR
23282c211eaSJuergen Gross	xen_hypercall_iret
23356415c4cSJuergen GrossSYM_CODE_END(xen_iret)
23456415c4cSJuergen Gross
23556415c4cSJuergen Gross/*
2365c8f6a2eSLai Jiangshan * XEN pv doesn't use trampoline stack, PER_CPU_VAR(cpu_tss_rw + TSS_sp0) is
2375c8f6a2eSLai Jiangshan * also the kernel stack.  Reusing swapgs_restore_regs_and_return_to_usermode()
2385c8f6a2eSLai Jiangshan * in XEN pv would cause %rsp to move up to the top of the kernel stack and
2395c8f6a2eSLai Jiangshan * leave the IRET frame below %rsp, which is dangerous to be corrupted if #NMI
2405c8f6a2eSLai Jiangshan * interrupts. And swapgs_restore_regs_and_return_to_usermode() pushing the IRET
2415c8f6a2eSLai Jiangshan * frame at the same address is useless.
2425c8f6a2eSLai Jiangshan */
2435c8f6a2eSLai JiangshanSYM_CODE_START(xenpv_restore_regs_and_return_to_usermode)
2445c8f6a2eSLai Jiangshan	UNWIND_HINT_REGS
2455c8f6a2eSLai Jiangshan	POP_REGS
2465c8f6a2eSLai Jiangshan
2475c8f6a2eSLai Jiangshan	/* stackleak_erase() can work safely on the kernel stack. */
2485c8f6a2eSLai Jiangshan	STACKLEAK_ERASE_NOCLOBBER
2495c8f6a2eSLai Jiangshan
2505c8f6a2eSLai Jiangshan	addq	$8, %rsp	/* skip regs->orig_ax */
2515c8f6a2eSLai Jiangshan	jmp xen_iret
2525c8f6a2eSLai JiangshanSYM_CODE_END(xenpv_restore_regs_and_return_to_usermode)
2535c8f6a2eSLai Jiangshan
2545c8f6a2eSLai Jiangshan/*
25556415c4cSJuergen Gross * Xen handles syscall callbacks much like ordinary exceptions, which
25656415c4cSJuergen Gross * means we have:
25756415c4cSJuergen Gross * - kernel gs
25856415c4cSJuergen Gross * - kernel rsp
25956415c4cSJuergen Gross * - an iret-like stack frame on the stack (including rcx and r11):
26056415c4cSJuergen Gross *	ss
26156415c4cSJuergen Gross *	rsp
26256415c4cSJuergen Gross *	rflags
26356415c4cSJuergen Gross *	cs
26456415c4cSJuergen Gross *	rip
26556415c4cSJuergen Gross *	r11
26656415c4cSJuergen Gross * rsp->rcx
26756415c4cSJuergen Gross */
26856415c4cSJuergen Gross
26956415c4cSJuergen Gross/* Normal 64-bit system call target */
270b75b7f8eSPeter ZijlstraSYM_CODE_START(xen_entry_SYSCALL_64)
271a09a6e23SPeter Zijlstra	UNWIND_HINT_ENTRY
2725b2fc515SPeter Zijlstra	ENDBR
27356415c4cSJuergen Gross	popq %rcx
27456415c4cSJuergen Gross	popq %r11
27556415c4cSJuergen Gross
27656415c4cSJuergen Gross	/*
27756415c4cSJuergen Gross	 * Neither Xen nor the kernel really knows what the old SS and
27856415c4cSJuergen Gross	 * CS were.  The kernel expects __USER_DS and __USER_CS, so
27956415c4cSJuergen Gross	 * report those values even though Xen will guess its own values.
28056415c4cSJuergen Gross	 */
28156415c4cSJuergen Gross	movq $__USER_DS, 4*8(%rsp)
28256415c4cSJuergen Gross	movq $__USER_CS, 1*8(%rsp)
28356415c4cSJuergen Gross
28456415c4cSJuergen Gross	jmp entry_SYSCALL_64_after_hwframe
285b75b7f8eSPeter ZijlstraSYM_CODE_END(xen_entry_SYSCALL_64)
28656415c4cSJuergen Gross
28756415c4cSJuergen Gross#ifdef CONFIG_IA32_EMULATION
28856415c4cSJuergen Gross
28956415c4cSJuergen Gross/* 32-bit compat syscall target */
290b75b7f8eSPeter ZijlstraSYM_CODE_START(xen_entry_SYSCALL_compat)
291a09a6e23SPeter Zijlstra	UNWIND_HINT_ENTRY
2925b2fc515SPeter Zijlstra	ENDBR
29356415c4cSJuergen Gross	popq %rcx
29456415c4cSJuergen Gross	popq %r11
29556415c4cSJuergen Gross
29656415c4cSJuergen Gross	/*
29756415c4cSJuergen Gross	 * Neither Xen nor the kernel really knows what the old SS and
298695c39bcSBrian Gerst	 * CS were.  The kernel expects __USER_DS and __USER32_CS, so
29956415c4cSJuergen Gross	 * report those values even though Xen will guess its own values.
30056415c4cSJuergen Gross	 */
301695c39bcSBrian Gerst	movq $__USER_DS, 4*8(%rsp)
30256415c4cSJuergen Gross	movq $__USER32_CS, 1*8(%rsp)
30356415c4cSJuergen Gross
30456415c4cSJuergen Gross	jmp entry_SYSCALL_compat_after_hwframe
305b75b7f8eSPeter ZijlstraSYM_CODE_END(xen_entry_SYSCALL_compat)
30656415c4cSJuergen Gross
30756415c4cSJuergen Gross/* 32-bit compat sysenter target */
308b75b7f8eSPeter ZijlstraSYM_CODE_START(xen_entry_SYSENTER_compat)
309a09a6e23SPeter Zijlstra	UNWIND_HINT_ENTRY
3105b2fc515SPeter Zijlstra	ENDBR
31156415c4cSJuergen Gross	/*
31256415c4cSJuergen Gross	 * NB: Xen is polite and clears TF from EFLAGS for us.  This means
31356415c4cSJuergen Gross	 * that we don't need to guard against single step exceptions here.
31456415c4cSJuergen Gross	 */
31556415c4cSJuergen Gross	popq %rcx
31656415c4cSJuergen Gross	popq %r11
31756415c4cSJuergen Gross
31856415c4cSJuergen Gross	/*
31956415c4cSJuergen Gross	 * Neither Xen nor the kernel really knows what the old SS and
320695c39bcSBrian Gerst	 * CS were.  The kernel expects __USER_DS and __USER32_CS, so
32156415c4cSJuergen Gross	 * report those values even though Xen will guess its own values.
32256415c4cSJuergen Gross	 */
323695c39bcSBrian Gerst	movq $__USER_DS, 4*8(%rsp)
32456415c4cSJuergen Gross	movq $__USER32_CS, 1*8(%rsp)
32556415c4cSJuergen Gross
32656415c4cSJuergen Gross	jmp entry_SYSENTER_compat_after_hwframe
327b75b7f8eSPeter ZijlstraSYM_CODE_END(xen_entry_SYSENTER_compat)
32856415c4cSJuergen Gross
32956415c4cSJuergen Gross#else /* !CONFIG_IA32_EMULATION */
33056415c4cSJuergen Gross
331b75b7f8eSPeter ZijlstraSYM_CODE_START(xen_entry_SYSCALL_compat)
332b75b7f8eSPeter ZijlstraSYM_CODE_START(xen_entry_SYSENTER_compat)
333a09a6e23SPeter Zijlstra	UNWIND_HINT_ENTRY
3345b2fc515SPeter Zijlstra	ENDBR
33556415c4cSJuergen Gross	lea 16(%rsp), %rsp	/* strip %rcx, %r11 */
33656415c4cSJuergen Gross	mov $-ENOSYS, %rax
33782c211eaSJuergen Gross	xen_hypercall_iret
338b75b7f8eSPeter ZijlstraSYM_CODE_END(xen_entry_SYSENTER_compat)
339b75b7f8eSPeter ZijlstraSYM_CODE_END(xen_entry_SYSCALL_compat)
34056415c4cSJuergen Gross
34156415c4cSJuergen Gross#endif	/* CONFIG_IA32_EMULATION */
342