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>
This commit is contained in:
parent
41f055d49c
commit
7042cb4eb3
|
@ -168,29 +168,28 @@ ENTRY(lg_restore_fl)
|
|||
* So we have to copy eflags from the stack to lguest_data.irq_enabled before
|
||||
* we do the "iret".
|
||||
*
|
||||
* There are two problems with this: firstly, we need to use a register to do
|
||||
* the copy and secondly, the whole thing needs to be atomic. The first
|
||||
* problem is easy to solve: push %eax on the stack so we can use it, and then
|
||||
* restore it at the end just before the real "iret".
|
||||
* There are two problems with this: firstly, we can't clobber any registers
|
||||
* and secondly, the whole thing needs to be atomic. The first problem
|
||||
* is solved by using "push memory"/"pop memory" instruction pair for copying.
|
||||
*
|
||||
* The second is harder: copying eflags to lguest_data.irq_enabled will turn
|
||||
* interrupts on before we're finished, so we could be interrupted before we
|
||||
* return to userspace or wherever. Our solution to this is to surround the
|
||||
* code with lguest_noirq_start: and lguest_noirq_end: labels. We tell the
|
||||
* Host that it is *never* to interrupt us there, even if interrupts seem to be
|
||||
* enabled.
|
||||
* enabled. (It's not necessary to protect pop instruction, since
|
||||
* data gets updated only after it completes, so we end up surrounding
|
||||
* just one instruction, iret).
|
||||
*/
|
||||
ENTRY(lguest_iret)
|
||||
pushl %eax
|
||||
movl 12(%esp), %eax
|
||||
lguest_noirq_start:
|
||||
pushl 2*4(%esp)
|
||||
/*
|
||||
* Note the %ss: segment prefix here. Normal data accesses use the
|
||||
* "ds" segment, but that will have already been restored for whatever
|
||||
* we're returning to (such as userspace): we can't trust it. The %ss:
|
||||
* prefix makes sure we use the stack segment, which is still valid.
|
||||
*/
|
||||
movl %eax,%ss:lguest_data+LGUEST_DATA_irq_enabled
|
||||
popl %eax
|
||||
popl %ss:lguest_data+LGUEST_DATA_irq_enabled
|
||||
lguest_noirq_start:
|
||||
iret
|
||||
lguest_noirq_end:
|
||||
|
|
Loading…
Reference in New Issue