x86/entry: Stop using PER_CPU_VAR(kernel_stack)
[cascardo/linux.git] / arch / x86 / xen / xen-asm_64.S
1 /*
2  * Asm versions of Xen pv-ops, suitable for either direct use or
3  * inlining.  The inline versions are the same as the direct-use
4  * versions, with the pre- and post-amble chopped off.
5  *
6  * This code is encoded for size rather than absolute efficiency, with
7  * a view to being able to inline as much as possible.
8  *
9  * We only bother with direct forms (ie, vcpu in pda) of the
10  * operations here; the indirect forms are better handled in C, since
11  * they're generally too large to inline anyway.
12  */
13
14 #include <asm/errno.h>
15 #include <asm/percpu.h>
16 #include <asm/processor-flags.h>
17 #include <asm/segment.h>
18 #include <asm/asm-offsets.h>
19
20 #include <xen/interface/xen.h>
21
22 #include "xen-asm.h"
23
24 ENTRY(xen_adjust_exception_frame)
25         mov 8+0(%rsp), %rcx
26         mov 8+8(%rsp), %r11
27         ret $16
28
29 hypercall_iret = hypercall_page + __HYPERVISOR_iret * 32
30 /*
31  * Xen64 iret frame:
32  *
33  *      ss
34  *      rsp
35  *      rflags
36  *      cs
37  *      rip             <-- standard iret frame
38  *
39  *      flags
40  *
41  *      rcx             }
42  *      r11             }<-- pushed by hypercall page
43  * rsp->rax             }
44  */
45 ENTRY(xen_iret)
46         pushq $0
47 1:      jmp hypercall_iret
48 ENDPATCH(xen_iret)
49 RELOC(xen_iret, 1b+1)
50
51 ENTRY(xen_sysret64)
52         /*
53          * We're already on the usermode stack at this point, but
54          * still with the kernel gs, so we can easily switch back
55          */
56         movq %rsp, PER_CPU_VAR(rsp_scratch)
57         movq PER_CPU_VAR(cpu_tss + TSS_sp0), %rsp
58
59         pushq $__USER_DS
60         pushq PER_CPU_VAR(rsp_scratch)
61         pushq %r11
62         pushq $__USER_CS
63         pushq %rcx
64
65         pushq $VGCF_in_syscall
66 1:      jmp hypercall_iret
67 ENDPATCH(xen_sysret64)
68 RELOC(xen_sysret64, 1b+1)
69
70 ENTRY(xen_sysret32)
71         /*
72          * We're already on the usermode stack at this point, but
73          * still with the kernel gs, so we can easily switch back
74          */
75         movq %rsp, PER_CPU_VAR(rsp_scratch)
76         movq PER_CPU_VAR(cpu_tss + TSS_sp0), %rsp
77
78         pushq $__USER32_DS
79         pushq PER_CPU_VAR(rsp_scratch)
80         pushq %r11
81         pushq $__USER32_CS
82         pushq %rcx
83
84         pushq $0
85 1:      jmp hypercall_iret
86 ENDPATCH(xen_sysret32)
87 RELOC(xen_sysret32, 1b+1)
88
89 /*
90  * Xen handles syscall callbacks much like ordinary exceptions, which
91  * means we have:
92  * - kernel gs
93  * - kernel rsp
94  * - an iret-like stack frame on the stack (including rcx and r11):
95  *      ss
96  *      rsp
97  *      rflags
98  *      cs
99  *      rip
100  *      r11
101  * rsp->rcx
102  *
103  * In all the entrypoints, we undo all that to make it look like a
104  * CPU-generated syscall/sysenter and jump to the normal entrypoint.
105  */
106
107 .macro undo_xen_syscall
108         mov 0*8(%rsp), %rcx
109         mov 1*8(%rsp), %r11
110         mov 5*8(%rsp), %rsp
111 .endm
112
113 /* Normal 64-bit system call target */
114 ENTRY(xen_syscall_target)
115         undo_xen_syscall
116         jmp system_call_after_swapgs
117 ENDPROC(xen_syscall_target)
118
119 #ifdef CONFIG_IA32_EMULATION
120
121 /* 32-bit compat syscall target */
122 ENTRY(xen_syscall32_target)
123         undo_xen_syscall
124         jmp ia32_cstar_target
125 ENDPROC(xen_syscall32_target)
126
127 /* 32-bit compat sysenter target */
128 ENTRY(xen_sysenter_target)
129         undo_xen_syscall
130         jmp ia32_sysenter_target
131 ENDPROC(xen_sysenter_target)
132
133 #else /* !CONFIG_IA32_EMULATION */
134
135 ENTRY(xen_syscall32_target)
136 ENTRY(xen_sysenter_target)
137         lea 16(%rsp), %rsp      /* strip %rcx, %r11 */
138         mov $-ENOSYS, %rax
139         pushq $0
140         jmp hypercall_iret
141 ENDPROC(xen_syscall32_target)
142 ENDPROC(xen_sysenter_target)
143
144 #endif  /* CONFIG_IA32_EMULATION */