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