blob: ebf610b49c0687e997d7ada1be17165c91edb5b2 [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 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>
David Brazdil0f672f62019-12-10 10:32:29 +000015#include <asm/asm.h>
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000016
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)
David Brazdil0f672f62019-12-10 10:32:29 +000028_ASM_NOKPROBE(xen_\name)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000029.endm
30
31xen_pv_trap divide_error
32xen_pv_trap debug
33xen_pv_trap xendebug
34xen_pv_trap int3
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000035xen_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
David Brazdil0f672f62019-12-10 10:32:29 +000095 * still with the kernel gs, so we can easily switch back.
96 *
97 * tss.sp2 is scratch space.
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000098 */
David Brazdil0f672f62019-12-10 10:32:29 +000099 movq %rsp, PER_CPU_VAR(cpu_tss_rw + TSS_sp2)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000100 movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
101
102 pushq $__USER_DS
David Brazdil0f672f62019-12-10 10:32:29 +0000103 pushq PER_CPU_VAR(cpu_tss_rw + TSS_sp2)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000104 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 */