__matt__ wrote:
The Linux kernel is mapped into each processes' virtual address space, usually starting at 3GB and running to 4GB (this is configurable; some people use a 2GB/2GB split). Why?
Linux has a 4G/4G patch which gives nearly the full 4GB to user-mode and kernel-mode. The top 16MB of the address space is common to the kernel address space and user address space.
http://lkml.org/lkml/2003/7/8/246
I'm not sure why it needs 16MB, it should take less than 4k of code for this "trampoline" and less than 4k of data for a GDT, IDT, a single TSS and a few extra variables to hold the k_EIP, k_ESP, k_EFLAGS and k_CR3 to use when switching to the kernel.
Say an interrupt occurs from user-mode, it enters the "trampoline kernel". The trampoline then switches to the kernel's CR3 and saves the user-mode EIP, ESP, EFLAGS and CR3 on the k_ESP "kernel personality stack".
It also saves the intitial value of k_ESP itself.
The "trampoline kernel" then does an IRET to begin executing in the "kernel personality address space" by using the k_EIP, k_ESP and k_EFLAGS and k_CR3 held in the kernel.
To return back to user mode another interrupt/syscall is needed to mimic the IRET. It uses the EIP, ESP, EFLAGS and CR3 that were popped onto the "kernel personality stack" to return to the user address space. The value of k_ESP is copied off the stack and stored in the trampoline for the next interrupt/syscall. This allows each task/thread to have a different stack in the "personality address space".
I hope I haven't confused you too much. It gets a bit confusing talking about a "kernel" in an address space "the personality", when you've also got a tiny kernel in every address space "the trampoline."
Interestingly you can think of it as a single-server microkernel a bit like L4Linux, except L4Linux is more complicated and uses an "active object model" which has a thread in the personality simulating the kernel half.
The above 4G-4G trampoline uses a "passive object model", the thread migrates from one address space to another. Many microkernels (such as Mach) have something similar, usually called "Migrating Threads" or LRPC (Lightweight remote procedure call).
The trampoline idea can be expanded with a few modifications to allow a thread to make a "lightweight remote procedure call" to one of many servers.
In alt.os.development KVP mentioned the above trampoline idea and I suggested some way of making it into a multi-server microkernel.
http://tinyurl.com/6gb5b
You might also want to do a search for "Linux: 4G/4G Overhead" or even the paper on L4Linux (since it is similar in some ways) to get an idea of the slowdown.