diff options
author | Denys Vlasenko <dvlasenk@redhat.com> | 2015-03-23 21:21:39 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2015-03-23 21:22:08 -0400 |
commit | 7042cb4eb30967b5eb9eeba04907882f04d6b6e5 (patch) | |
tree | 3a7412f92a18e518395da0627dc7565b3a625f58 | |
parent | 41f055d49cb04d648a89a2cb6d57c94ff86d5bb6 (diff) |
lguest: simplify lguest_iret
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
CC: lguest@lists.ozlabs.org
CC: x86@kernel.org
CC: linux-kernel@vger.kernel.org
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r-- | arch/x86/lguest/head_32.S | 19 |
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 | */ |
183 | ENTRY(lguest_iret) | 184 | ENTRY(lguest_iret) |
184 | pushl %eax | 185 | pushl 2*4(%esp) |
185 | movl 12(%esp), %eax | ||
186 | lguest_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 | 193 | lguest_noirq_start: |
195 | iret | 194 | iret |
196 | lguest_noirq_end: | 195 | lguest_noirq_end: |