This is my guess:
esp0 is initialized with the kernel stack top addr. when the kernel stack is allocated, and it is used, during process switch, to initialize tss->esp0, so that when context switches from user mode to kernel mode, the kernel stack can be located; while esp is used to save the kernel stack top of the process that is to be scheduled out during process switch.
So esp0 in a thread_struct doesn't change once initialized, while esp changes.
Is my guess right?
The thread_struct structure contains two of these ESP fields, those being esp0 and esp. However, they relate to the four fields in the tss_segment_32 structure, those being esp0, esp1, esp2 and esp.
These actually exist in the TSS so it's very much something from Intel rather than something from Linus et al.
As to why the TSS contains them, the numbers are logical if you know how the protection model works under x86. They are, in fact, the ring levels (except for esp which is for ring level 3 despite the fact it's not actually called esp3).
In other words, they contain the stack pointer to be used in the ring that you're executing in. Since Linux only uses ring 0 (kernel mode) and ring 3 (user mode), esp0 and esp are the only ones that need to be saved.
As an aside, I think the only OS I've ever seen use another ring was OS/2 which used ring 2 for certain I/O operations. Processes that were allowed to perform those operations had to be specially marked and the OS would run them in ring 2 to allow unfettered I/O access, without being allowed to bring down the kernel.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With