Information Technology Reference
In-Depth Information
One small difference.
You may notice that in Chapter 2, for a mode switch the x86 hardware saved not
just the instruction pointer and
eflags
register but also the the stack pointer of the
interrupted process before starting the handler. In the mode switch case, the hardware
changed the stack pointer to the kernel's exception stack, so it must save the original
stack pointer.
In contrast, when we switch from a kernel thread to a kernel handler—as we do for
a thread context switch initiated by either a library call or an interrupt—the hardware
does not switch stacks. Instead, the handler runs on the current stack not a separate
exception stack. Therefore, the hardware does not need to save the original stack
pointer; the handler just saves the stack pointer with the other registers as part of the
pushad
instruction.
Thus, x86 hardware thus works a bit differently when switching between a kernel
thread and a kernel handler than when doing a mode switch.
Entering the handler. When an interrupt or exception occurs, if the processor
detects that it is already in kernel mode (by inspecting the
eflags
register), it just
pushes the instruction pointer and
eflags
registers (but not the stack pointer)
onto the existing stack.
On the other hand, if the hardware detects that it is switching from user mode
to kernel mode, then the processor also changes the stack pointer to the base of
the exception stack and pushes the original stack pointer aong with the instruction
pointer and
eflags
registers onto the new stack.
Returning from the handler. When the
iret
instruction is called, it inspects
both the current
eflags
register and the value on the stack that is will use to
restore the earlier
eflags
register. If the mode bit is identical, then
iret
just pops
the instruction pointer and
eflags
register and continues to use the current stack.
On the other hand, if the mode bit differs, then the
iret
instruction pops not only
the instruction pointer and
eflags
register, but also the saved stack pointer, thus
switching the processor's stack pointer to the saved one.
To be compatible with this x86 hardware behavior, our software implementation of
threadyield
for in-kernel threads simulates the hardware case, saving only the in-
struction pointer and
eflags
register before calling
pushad
to save the general-purpose
registers (including the stack pointer.) Now,
iret
will work properly whether the kernel
thread it is resuming was suspended by a hardware event or a software call.