summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/lguest/head_32.S19
1 files changed, 9 insertions, 10 deletions
diff --git a/arch/x86/lguest/head_32.S b/arch/x86/lguest/head_32.S
index 05b0a85507ce..81678bf0fcb7 100644
--- a/arch/x86/lguest/head_32.S
+++ b/arch/x86/lguest/head_32.S
@@ -168,29 +168,28 @@ ENTRY(lg_restore_fl)
168 * So we have to copy eflags from the stack to lguest_data.irq_enabled before 168 * So we have to copy eflags from the stack to lguest_data.irq_enabled before
169 * we do the "iret". 169 * we do the "iret".
170 * 170 *
171 * There are two problems with this: firstly, we need to use a register to do 171 * There are two problems with this: firstly, we can't clobber any registers
172 * the copy and secondly, the whole thing needs to be atomic. The first 172 * and secondly, the whole thing needs to be atomic. The first problem
173 * problem is easy to solve: push %eax on the stack so we can use it, and then 173 * is solved by using "push memory"/"pop memory" instruction pair for copying.
174 * restore it at the end just before the real "iret".
175 * 174 *
176 * The second is harder: copying eflags to lguest_data.irq_enabled will turn 175 * The second is harder: copying eflags to lguest_data.irq_enabled will turn
177 * interrupts on before we're finished, so we could be interrupted before we 176 * interrupts on before we're finished, so we could be interrupted before we
178 * return to userspace or wherever. Our solution to this is to surround the 177 * return to userspace or wherever. Our solution to this is to surround the
179 * code with lguest_noirq_start: and lguest_noirq_end: labels. We tell the 178 * code with lguest_noirq_start: and lguest_noirq_end: labels. We tell the
180 * Host that it is *never* to interrupt us there, even if interrupts seem to be 179 * Host that it is *never* to interrupt us there, even if interrupts seem to be
181 * enabled. 180 * enabled. (It's not necessary to protect pop instruction, since
181 * data gets updated only after it completes, so we end up surrounding
182 * just one instruction, iret).
182 */ 183 */
183ENTRY(lguest_iret) 184ENTRY(lguest_iret)
184 pushl %eax 185 pushl 2*4(%esp)
185 movl 12(%esp), %eax
186lguest_noirq_start:
187 /* 186 /*
188 * Note the %ss: segment prefix here. Normal data accesses use the 187 * Note the %ss: segment prefix here. Normal data accesses use the
189 * "ds" segment, but that will have already been restored for whatever 188 * "ds" segment, but that will have already been restored for whatever
190 * we're returning to (such as userspace): we can't trust it. The %ss: 189 * we're returning to (such as userspace): we can't trust it. The %ss:
191 * prefix makes sure we use the stack segment, which is still valid. 190 * prefix makes sure we use the stack segment, which is still valid.
192 */ 191 */
193 movl %eax,%ss:lguest_data+LGUEST_DATA_irq_enabled 192 popl %ss:lguest_data+LGUEST_DATA_irq_enabled
194 popl %eax 193lguest_noirq_start:
195 iret 194 iret
196lguest_noirq_end: 195lguest_noirq_end: