linux/arch/x86/xen/xen-asm_64.S
<<
>>
Prefs
   1/* 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 pda) of the
   6 * operations here; the indirect forms are better handled in C.
   7 */
   8
   9#include <asm/errno.h>
  10#include <asm/percpu.h>
  11#include <asm/processor-flags.h>
  12#include <asm/segment.h>
  13#include <asm/asm-offsets.h>
  14#include <asm/thread_info.h>
  15#include <asm/asm.h>
  16
  17#include <xen/interface/xen.h>
  18
  19#include <linux/init.h>
  20#include <linux/linkage.h>
  21
  22.macro xen_pv_trap name
  23ENTRY(xen_\name)
  24        pop %rcx
  25        pop %r11
  26        jmp  \name
  27END(xen_\name)
  28_ASM_NOKPROBE(xen_\name)
  29.endm
  30
  31xen_pv_trap divide_error
  32xen_pv_trap debug
  33xen_pv_trap xendebug
  34xen_pv_trap int3
  35xen_pv_trap xennmi
  36xen_pv_trap overflow
  37xen_pv_trap bounds
  38xen_pv_trap invalid_op
  39xen_pv_trap device_not_available
  40xen_pv_trap double_fault
  41xen_pv_trap coprocessor_segment_overrun
  42xen_pv_trap invalid_TSS
  43xen_pv_trap segment_not_present
  44xen_pv_trap stack_segment
  45xen_pv_trap general_protection
  46xen_pv_trap page_fault
  47xen_pv_trap spurious_interrupt_bug
  48xen_pv_trap coprocessor_error
  49xen_pv_trap alignment_check
  50#ifdef CONFIG_X86_MCE
  51xen_pv_trap machine_check
  52#endif /* CONFIG_X86_MCE */
  53xen_pv_trap simd_coprocessor_error
  54#ifdef CONFIG_IA32_EMULATION
  55xen_pv_trap entry_INT80_compat
  56#endif
  57xen_pv_trap hypervisor_callback
  58
  59        __INIT
  60ENTRY(xen_early_idt_handler_array)
  61        i = 0
  62        .rept NUM_EXCEPTION_VECTORS
  63        pop %rcx
  64        pop %r11
  65        jmp early_idt_handler_array + i*EARLY_IDT_HANDLER_SIZE
  66        i = i + 1
  67        .fill xen_early_idt_handler_array + i*XEN_EARLY_IDT_HANDLER_SIZE - ., 1, 0xcc
  68        .endr
  69END(xen_early_idt_handler_array)
  70        __FINIT
  71
  72hypercall_iret = hypercall_page + __HYPERVISOR_iret * 32
  73/*
  74 * Xen64 iret frame:
  75 *
  76 *      ss
  77 *      rsp
  78 *      rflags
  79 *      cs
  80 *      rip             <-- standard iret frame
  81 *
  82 *      flags
  83 *
  84 *      rcx             }
  85 *      r11             }<-- pushed by hypercall page
  86 * rsp->rax             }
  87 */
  88ENTRY(xen_iret)
  89        pushq $0
  90        jmp hypercall_iret
  91
  92ENTRY(xen_sysret64)
  93        /*
  94         * We're already on the usermode stack at this point, but
  95         * still with the kernel gs, so we can easily switch back.
  96         *
  97         * tss.sp2 is scratch space.
  98         */
  99        movq %rsp, PER_CPU_VAR(cpu_tss_rw + TSS_sp2)
 100        movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
 101
 102        pushq $__USER_DS
 103        pushq PER_CPU_VAR(cpu_tss_rw + TSS_sp2)
 104        pushq %r11
 105        pushq $__USER_CS
 106        pushq %rcx
 107
 108        pushq $VGCF_in_syscall
 109        jmp hypercall_iret
 110
 111/*
 112 * Xen handles syscall callbacks much like ordinary exceptions, which
 113 * means we have:
 114 * - kernel gs
 115 * - kernel rsp
 116 * - an iret-like stack frame on the stack (including rcx and r11):
 117 *      ss
 118 *      rsp
 119 *      rflags
 120 *      cs
 121 *      rip
 122 *      r11
 123 * rsp->rcx
 124 */
 125
 126/* Normal 64-bit system call target */
 127ENTRY(xen_syscall_target)
 128        popq %rcx
 129        popq %r11
 130
 131        /*
 132         * Neither Xen nor the kernel really knows what the old SS and
 133         * CS were.  The kernel expects __USER_DS and __USER_CS, so
 134         * report those values even though Xen will guess its own values.
 135         */
 136        movq $__USER_DS, 4*8(%rsp)
 137        movq $__USER_CS, 1*8(%rsp)
 138
 139        jmp entry_SYSCALL_64_after_hwframe
 140ENDPROC(xen_syscall_target)
 141
 142#ifdef CONFIG_IA32_EMULATION
 143
 144/* 32-bit compat syscall target */
 145ENTRY(xen_syscall32_target)
 146        popq %rcx
 147        popq %r11
 148
 149        /*
 150         * Neither Xen nor the kernel really knows what the old SS and
 151         * CS were.  The kernel expects __USER32_DS and __USER32_CS, so
 152         * report those values even though Xen will guess its own values.
 153         */
 154        movq $__USER32_DS, 4*8(%rsp)
 155        movq $__USER32_CS, 1*8(%rsp)
 156
 157        jmp entry_SYSCALL_compat_after_hwframe
 158ENDPROC(xen_syscall32_target)
 159
 160/* 32-bit compat sysenter target */
 161ENTRY(xen_sysenter_target)
 162        mov 0*8(%rsp), %rcx
 163        mov 1*8(%rsp), %r11
 164        mov 5*8(%rsp), %rsp
 165        jmp entry_SYSENTER_compat
 166ENDPROC(xen_sysenter_target)
 167
 168#else /* !CONFIG_IA32_EMULATION */
 169
 170ENTRY(xen_syscall32_target)
 171ENTRY(xen_sysenter_target)
 172        lea 16(%rsp), %rsp      /* strip %rcx, %r11 */
 173        mov $-ENOSYS, %rax
 174        pushq $0
 175        jmp hypercall_iret
 176ENDPROC(xen_syscall32_target)
 177ENDPROC(xen_sysenter_target)
 178
 179#endif  /* CONFIG_IA32_EMULATION */
 180