Commit | Line | Data |
---|---|---|
6487673b | 1 | /* |
130ace11 TH |
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. | |
6487673b JF |
12 | */ |
13 | ||
6487673b | 14 | #include <asm/thread_info.h> |
6487673b | 15 | #include <asm/processor-flags.h> |
9ec2b804 JF |
16 | #include <asm/segment.h> |
17 | ||
18 | #include <xen/interface/xen.h> | |
6487673b | 19 | |
5393744b | 20 | #include "xen-asm.h" |
6487673b JF |
21 | |
22 | /* | |
130ace11 TH |
23 | * Force an event check by making a hypercall, but preserve regs |
24 | * before making the call. | |
6487673b | 25 | */ |
5393744b JF |
26 | check_events: |
27 | push %eax | |
28 | push %ecx | |
29 | push %edx | |
30 | call xen_force_evtchn_callback | |
31 | pop %edx | |
32 | pop %ecx | |
33 | pop %eax | |
6487673b | 34 | ret |
6487673b | 35 | |
b77797fb | 36 | /* |
130ace11 TH |
37 | * We can't use sysexit directly, because we're not running in ring0. |
38 | * But we can easily fake it up using iret. Assuming xen_sysexit is | |
39 | * jumped to with a standard stack frame, we can just strip it back to | |
40 | * a standard iret frame and use iret. | |
b77797fb JF |
41 | */ |
42 | ENTRY(xen_sysexit) | |
43 | movl PT_EAX(%esp), %eax /* Shouldn't be necessary? */ | |
44 | orl $X86_EFLAGS_IF, PT_EFLAGS(%esp) | |
45 | lea PT_EIP(%esp), %esp | |
46 | ||
47 | jmp xen_iret | |
48 | ENDPROC(xen_sysexit) | |
49 | ||
9ec2b804 | 50 | /* |
130ace11 TH |
51 | * This is run where a normal iret would be run, with the same stack setup: |
52 | * 8: eflags | |
53 | * 4: cs | |
54 | * esp-> 0: eip | |
55 | * | |
56 | * This attempts to make sure that any pending events are dealt with | |
57 | * on return to usermode, but there is a small window in which an | |
58 | * event can happen just before entering usermode. If the nested | |
59 | * interrupt ends up setting one of the TIF_WORK_MASK pending work | |
60 | * flags, they will not be tested again before returning to | |
61 | * usermode. This means that a process can end up with pending work, | |
62 | * which will be unprocessed until the process enters and leaves the | |
63 | * kernel again, which could be an unbounded amount of time. This | |
64 | * means that a pending signal or reschedule event could be | |
65 | * indefinitely delayed. | |
66 | * | |
67 | * The fix is to notice a nested interrupt in the critical window, and | |
68 | * if one occurs, then fold the nested interrupt into the current | |
69 | * interrupt stack frame, and re-process it iteratively rather than | |
70 | * recursively. This means that it will exit via the normal path, and | |
71 | * all pending work will be dealt with appropriately. | |
72 | * | |
73 | * Because the nested interrupt handler needs to deal with the current | |
74 | * stack state in whatever form its in, we keep things simple by only | |
75 | * using a single register which is pushed/popped on the stack. | |
9ec2b804 | 76 | */ |
81e103f1 | 77 | ENTRY(xen_iret) |
9ec2b804 JF |
78 | /* test eflags for special cases */ |
79 | testl $(X86_EFLAGS_VM | XEN_EFLAGS_NMI), 8(%esp) | |
80 | jnz hyper_iret | |
81 | ||
82 | push %eax | |
83 | ESP_OFFSET=4 # bytes pushed onto stack | |
84 | ||
130ace11 TH |
85 | /* |
86 | * Store vcpu_info pointer for easy access. Do it this way to | |
87 | * avoid having to reload %fs | |
88 | */ | |
9ec2b804 JF |
89 | #ifdef CONFIG_SMP |
90 | GET_THREAD_INFO(%eax) | |
130ace11 TH |
91 | movl TI_cpu(%eax), %eax |
92 | movl __per_cpu_offset(,%eax,4), %eax | |
93 | mov per_cpu__xen_vcpu(%eax), %eax | |
9ec2b804 | 94 | #else |
81e103f1 | 95 | movl per_cpu__xen_vcpu, %eax |
9ec2b804 JF |
96 | #endif |
97 | ||
98 | /* check IF state we're restoring */ | |
99 | testb $X86_EFLAGS_IF>>8, 8+1+ESP_OFFSET(%esp) | |
100 | ||
130ace11 TH |
101 | /* |
102 | * Maybe enable events. Once this happens we could get a | |
103 | * recursive event, so the critical region starts immediately | |
104 | * afterwards. However, if that happens we don't end up | |
105 | * resuming the code, so we don't have to be worried about | |
106 | * being preempted to another CPU. | |
107 | */ | |
9ec2b804 JF |
108 | setz XEN_vcpu_info_mask(%eax) |
109 | xen_iret_start_crit: | |
110 | ||
111 | /* check for unmasked and pending */ | |
112 | cmpw $0x0001, XEN_vcpu_info_pending(%eax) | |
113 | ||
130ace11 TH |
114 | /* |
115 | * If there's something pending, mask events again so we can | |
116 | * jump back into xen_hypervisor_callback | |
117 | */ | |
9ec2b804 JF |
118 | sete XEN_vcpu_info_mask(%eax) |
119 | ||
120 | popl %eax | |
121 | ||
130ace11 TH |
122 | /* |
123 | * From this point on the registers are restored and the stack | |
124 | * updated, so we don't need to worry about it if we're | |
125 | * preempted | |
126 | */ | |
9ec2b804 JF |
127 | iret_restore_end: |
128 | ||
130ace11 TH |
129 | /* |
130 | * Jump to hypervisor_callback after fixing up the stack. | |
131 | * Events are masked, so jumping out of the critical region is | |
132 | * OK. | |
133 | */ | |
9ec2b804 JF |
134 | je xen_hypervisor_callback |
135 | ||
90e9f536 | 136 | 1: iret |
9ec2b804 | 137 | xen_iret_end_crit: |
130ace11 | 138 | .section __ex_table, "a" |
90e9f536 | 139 | .align 4 |
130ace11 | 140 | .long 1b, iret_exc |
90e9f536 | 141 | .previous |
9ec2b804 JF |
142 | |
143 | hyper_iret: | |
144 | /* put this out of line since its very rarely used */ | |
145 | jmp hypercall_page + __HYPERVISOR_iret * 32 | |
146 | ||
147 | .globl xen_iret_start_crit, xen_iret_end_crit | |
148 | ||
149 | /* | |
130ace11 TH |
150 | * This is called by xen_hypervisor_callback in entry.S when it sees |
151 | * that the EIP at the time of interrupt was between | |
152 | * xen_iret_start_crit and xen_iret_end_crit. We're passed the EIP in | |
153 | * %eax so we can do a more refined determination of what to do. | |
154 | * | |
155 | * The stack format at this point is: | |
156 | * ---------------- | |
157 | * ss : (ss/esp may be present if we came from usermode) | |
158 | * esp : | |
159 | * eflags } outer exception info | |
160 | * cs } | |
161 | * eip } | |
162 | * ---------------- <- edi (copy dest) | |
163 | * eax : outer eax if it hasn't been restored | |
164 | * ---------------- | |
165 | * eflags } nested exception info | |
166 | * cs } (no ss/esp because we're nested | |
167 | * eip } from the same ring) | |
168 | * orig_eax }<- esi (copy src) | |
169 | * - - - - - - - - | |
170 | * fs } | |
171 | * es } | |
172 | * ds } SAVE_ALL state | |
173 | * eax } | |
174 | * : : | |
175 | * ebx }<- esp | |
176 | * ---------------- | |
177 | * | |
178 | * In order to deliver the nested exception properly, we need to shift | |
179 | * everything from the return addr up to the error code so it sits | |
180 | * just under the outer exception info. This means that when we | |
181 | * handle the exception, we do it in the context of the outer | |
182 | * exception rather than starting a new one. | |
183 | * | |
184 | * The only caveat is that if the outer eax hasn't been restored yet | |
185 | * (ie, it's still on stack), we need to insert its value into the | |
186 | * SAVE_ALL state before going on, since it's usermode state which we | |
187 | * eventually need to restore. | |
9ec2b804 JF |
188 | */ |
189 | ENTRY(xen_iret_crit_fixup) | |
9ec2b804 | 190 | /* |
130ace11 TH |
191 | * Paranoia: Make sure we're really coming from kernel space. |
192 | * One could imagine a case where userspace jumps into the | |
193 | * critical range address, but just before the CPU delivers a | |
194 | * GP, it decides to deliver an interrupt instead. Unlikely? | |
195 | * Definitely. Easy to avoid? Yes. The Intel documents | |
196 | * explicitly say that the reported EIP for a bad jump is the | |
197 | * jump instruction itself, not the destination, but some | |
198 | * virtual environments get this wrong. | |
9ec2b804 | 199 | */ |
0f2c8769 | 200 | movl PT_CS(%esp), %ecx |
9ec2b804 JF |
201 | andl $SEGMENT_RPL_MASK, %ecx |
202 | cmpl $USER_RPL, %ecx | |
203 | je 2f | |
204 | ||
0f2c8769 JF |
205 | lea PT_ORIG_EAX(%esp), %esi |
206 | lea PT_EFLAGS(%esp), %edi | |
9ec2b804 | 207 | |
130ace11 TH |
208 | /* |
209 | * If eip is before iret_restore_end then stack | |
210 | * hasn't been restored yet. | |
211 | */ | |
9ec2b804 JF |
212 | cmp $iret_restore_end, %eax |
213 | jae 1f | |
214 | ||
130ace11 | 215 | movl 0+4(%edi), %eax /* copy EAX (just above top of frame) */ |
0f2c8769 | 216 | movl %eax, PT_EAX(%esp) |
9ec2b804 | 217 | |
130ace11 | 218 | lea ESP_OFFSET(%edi), %edi /* move dest up over saved regs */ |
9ec2b804 JF |
219 | |
220 | /* set up the copy */ | |
221 | 1: std | |
0f2c8769 | 222 | mov $PT_EIP / 4, %ecx /* saved regs up to orig_eax */ |
9ec2b804 JF |
223 | rep movsl |
224 | cld | |
225 | ||
130ace11 | 226 | lea 4(%edi), %esp /* point esp to new frame */ |
0f2c8769 | 227 | 2: jmp xen_do_upcall |
6487673b | 228 |