Merge branch 'i2c/for-mergewindow' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / arch / x86 / xen / xen-asm.S
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 percpu data) of the
6  * operations here; the indirect forms are better handled in C.
7  */
8
9 #include <asm/errno.h>
10 #include <asm/asm-offsets.h>
11 #include <asm/percpu.h>
12 #include <asm/processor-flags.h>
13 #include <asm/segment.h>
14 #include <asm/thread_info.h>
15 #include <asm/asm.h>
16 #include <asm/frame.h>
17 #include <asm/unwind_hints.h>
18
19 #include <xen/interface/xen.h>
20
21 #include <linux/init.h>
22 #include <linux/linkage.h>
23
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  */
29 SYM_FUNC_START(xen_irq_enable_direct)
30         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
45 1:
46         FRAME_END
47         ret
48 SYM_FUNC_END(xen_irq_enable_direct)
49
50
51 /*
52  * Disabling events is simply a matter of making the event mask
53  * non-zero.
54  */
55 SYM_FUNC_START(xen_irq_disable_direct)
56         movb $1, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask
57         ret
58 SYM_FUNC_END(xen_irq_disable_direct)
59
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  */
69 SYM_FUNC_START(xen_save_fl_direct)
70         testb $0xff, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask
71         setz %ah
72         addb %ah, %ah
73         ret
74 SYM_FUNC_END(xen_save_fl_direct)
75
76 /*
77  * Force an event check by making a hypercall, but preserve regs
78  * before making the call.
79  */
80 SYM_FUNC_START(check_events)
81         FRAME_BEGIN
82         push %rax
83         push %rcx
84         push %rdx
85         push %rsi
86         push %rdi
87         push %r8
88         push %r9
89         push %r10
90         push %r11
91         call xen_force_evtchn_callback
92         pop %r11
93         pop %r10
94         pop %r9
95         pop %r8
96         pop %rdi
97         pop %rsi
98         pop %rdx
99         pop %rcx
100         pop %rax
101         FRAME_END
102         ret
103 SYM_FUNC_END(check_events)
104
105 SYM_FUNC_START(xen_read_cr2)
106         FRAME_BEGIN
107         _ASM_MOV PER_CPU_VAR(xen_vcpu), %_ASM_AX
108         _ASM_MOV XEN_vcpu_info_arch_cr2(%_ASM_AX), %_ASM_AX
109         FRAME_END
110         ret
111 SYM_FUNC_END(xen_read_cr2);
112
113 SYM_FUNC_START(xen_read_cr2_direct)
114         FRAME_BEGIN
115         _ASM_MOV PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_arch_cr2, %_ASM_AX
116         FRAME_END
117         ret
118 SYM_FUNC_END(xen_read_cr2_direct);
119
120 .macro xen_pv_trap name
121 SYM_CODE_START(xen_\name)
122         UNWIND_HINT_EMPTY
123         pop %rcx
124         pop %r11
125         jmp  \name
126 SYM_CODE_END(xen_\name)
127 _ASM_NOKPROBE(xen_\name)
128 .endm
129
130 xen_pv_trap asm_exc_divide_error
131 xen_pv_trap asm_xenpv_exc_debug
132 xen_pv_trap asm_exc_int3
133 xen_pv_trap asm_xenpv_exc_nmi
134 xen_pv_trap asm_exc_overflow
135 xen_pv_trap asm_exc_bounds
136 xen_pv_trap asm_exc_invalid_op
137 xen_pv_trap asm_exc_device_not_available
138 xen_pv_trap asm_xenpv_exc_double_fault
139 xen_pv_trap asm_exc_coproc_segment_overrun
140 xen_pv_trap asm_exc_invalid_tss
141 xen_pv_trap asm_exc_segment_not_present
142 xen_pv_trap asm_exc_stack_segment
143 xen_pv_trap asm_exc_general_protection
144 xen_pv_trap asm_exc_page_fault
145 xen_pv_trap asm_exc_spurious_interrupt_bug
146 xen_pv_trap asm_exc_coprocessor_error
147 xen_pv_trap asm_exc_alignment_check
148 #ifdef CONFIG_X86_MCE
149 xen_pv_trap asm_xenpv_exc_machine_check
150 #endif /* CONFIG_X86_MCE */
151 xen_pv_trap asm_exc_simd_coprocessor_error
152 #ifdef CONFIG_IA32_EMULATION
153 xen_pv_trap entry_INT80_compat
154 #endif
155 xen_pv_trap asm_exc_xen_unknown_trap
156 xen_pv_trap asm_exc_xen_hypervisor_callback
157
158         __INIT
159 SYM_CODE_START(xen_early_idt_handler_array)
160         i = 0
161         .rept NUM_EXCEPTION_VECTORS
162         UNWIND_HINT_EMPTY
163         pop %rcx
164         pop %r11
165         jmp early_idt_handler_array + i*EARLY_IDT_HANDLER_SIZE
166         i = i + 1
167         .fill xen_early_idt_handler_array + i*XEN_EARLY_IDT_HANDLER_SIZE - ., 1, 0xcc
168         .endr
169 SYM_CODE_END(xen_early_idt_handler_array)
170         __FINIT
171
172 hypercall_iret = hypercall_page + __HYPERVISOR_iret * 32
173 /*
174  * Xen64 iret frame:
175  *
176  *      ss
177  *      rsp
178  *      rflags
179  *      cs
180  *      rip             <-- standard iret frame
181  *
182  *      flags
183  *
184  *      rcx             }
185  *      r11             }<-- pushed by hypercall page
186  * rsp->rax             }
187  */
188 SYM_CODE_START(xen_iret)
189         UNWIND_HINT_EMPTY
190         pushq $0
191         jmp hypercall_iret
192 SYM_CODE_END(xen_iret)
193
194 /*
195  * Xen handles syscall callbacks much like ordinary exceptions, which
196  * means we have:
197  * - kernel gs
198  * - kernel rsp
199  * - an iret-like stack frame on the stack (including rcx and r11):
200  *      ss
201  *      rsp
202  *      rflags
203  *      cs
204  *      rip
205  *      r11
206  * rsp->rcx
207  */
208
209 /* Normal 64-bit system call target */
210 SYM_CODE_START(xen_syscall_target)
211         UNWIND_HINT_EMPTY
212         popq %rcx
213         popq %r11
214
215         /*
216          * Neither Xen nor the kernel really knows what the old SS and
217          * CS were.  The kernel expects __USER_DS and __USER_CS, so
218          * report those values even though Xen will guess its own values.
219          */
220         movq $__USER_DS, 4*8(%rsp)
221         movq $__USER_CS, 1*8(%rsp)
222
223         jmp entry_SYSCALL_64_after_hwframe
224 SYM_CODE_END(xen_syscall_target)
225
226 #ifdef CONFIG_IA32_EMULATION
227
228 /* 32-bit compat syscall target */
229 SYM_CODE_START(xen_syscall32_target)
230         UNWIND_HINT_EMPTY
231         popq %rcx
232         popq %r11
233
234         /*
235          * Neither Xen nor the kernel really knows what the old SS and
236          * CS were.  The kernel expects __USER32_DS and __USER32_CS, so
237          * report those values even though Xen will guess its own values.
238          */
239         movq $__USER32_DS, 4*8(%rsp)
240         movq $__USER32_CS, 1*8(%rsp)
241
242         jmp entry_SYSCALL_compat_after_hwframe
243 SYM_CODE_END(xen_syscall32_target)
244
245 /* 32-bit compat sysenter target */
246 SYM_CODE_START(xen_sysenter_target)
247         UNWIND_HINT_EMPTY
248         /*
249          * NB: Xen is polite and clears TF from EFLAGS for us.  This means
250          * that we don't need to guard against single step exceptions here.
251          */
252         popq %rcx
253         popq %r11
254
255         /*
256          * Neither Xen nor the kernel really knows what the old SS and
257          * CS were.  The kernel expects __USER32_DS and __USER32_CS, so
258          * report those values even though Xen will guess its own values.
259          */
260         movq $__USER32_DS, 4*8(%rsp)
261         movq $__USER32_CS, 1*8(%rsp)
262
263         jmp entry_SYSENTER_compat_after_hwframe
264 SYM_CODE_END(xen_sysenter_target)
265
266 #else /* !CONFIG_IA32_EMULATION */
267
268 SYM_CODE_START(xen_syscall32_target)
269 SYM_CODE_START(xen_sysenter_target)
270         UNWIND_HINT_EMPTY
271         lea 16(%rsp), %rsp      /* strip %rcx, %r11 */
272         mov $-ENOSYS, %rax
273         pushq $0
274         jmp hypercall_iret
275 SYM_CODE_END(xen_sysenter_target)
276 SYM_CODE_END(xen_syscall32_target)
277
278 #endif  /* CONFIG_IA32_EMULATION */