There is now only one kernel stack, and therefore no stack-switching inside
the kernel.
On each inactive thread, we store the full state of all registers; this means
that functions can see them directly, and easily edit the user thread's
state.
This feature is used in the keyboard driver, where the keyboard interrupt now
writes the key directly into the return value (in %rax). Because of this,
there is now no logic performed in that thread after it wakes up---which is
good, because in this design there's no good way for that logic to occur.
Interrupt handlers never return; instead they eventually call
'enter_userspace', which goes to userspace itself by manufacturing a stack
and returning on it.
Specifcally, it uses the 'saved registers' in the TCB /as a stack/. Do not
change the order of the registers in that struct!
Fork is much simpler now, and uses no assembly at all.
Syscalls now preserve all registers (except for %rax, of course). We don't
necessarily need to guarantee it, but it would take actual work to not
preserve those registers.
We should merge the IPC code first; I'll rebase this on top of it once it's in.
We should merge the IPC code first; I'll rebase this on top of it once it's in.