KernelModeStackLayout
On the x86 platform:
highest +-------------+ STACK BASE address | | | | | | FPU save | the user-mode FPU context is flushed here whenever p | | area |<- necessary. The base address of this area is a fixed u | | | offset from the user-mode trap frame (see below) s | | | h | | | | |-------------| v | V86 segm. |<- the stack pointer for ring 0 in the V86 TSS points | selectors | here. Upon entering ring 0, the CPU first pushes the | | V86 segments, then the usual EFLAGS and CS:EIP | | | | |-------------| | EFLAGS, |<- the stack pointer for ring 0 in the TSS points here. | CS:EIP | Upon entering ring 0, the CPU pushes EFLAGS and | | CS:EIP starting from here | | | | |-------------| | | | ring 3 | | context |<- the trap frame is built by the trap handlers. It also | | (conceptually) includes the registers pushed by the | | CPU as part of a trap (V86 segments, EFLAGS, etc.). | | See the definition of the KTRAP_FRAME structure for | | reference . . . . . . | | | |<- the USER-MODE TRAP FRAME begins here. Since all the |-------------| structures above have a fixed size, this address is a | | fixed offset from the stack base (there is no other | | way to retrieve this pointer than adding said fixed . . offset to the stack base, in fact) . . . . | | Nested trap scenario (think system call): | | |-------------| | |<- the CPU begins pushing EFLAGS and CS:EIP from here. | | No need to use the stack pointer in the TSS because . . we didn't change the current ring. The trap handler . . finishes building the trap frame as usual . . | | | |<- the CURRENT TRAP FRAME begins here. The current |-------------| thread's TrapFrame is updated to point here, and the | | previous value is stored in TrapFrame->Edx | | | | | | | | lowest | | address +-------------+ STACK LIMIT