On 02/10/07 09:11, [EMAIL PROTECTED] wrote:
The %g7 register is setup by the trap code. On sun4u, user_trap()
determines the CPU->cpu_thread, stashes it in %l6 and calls utl0(). The
code in utl0() moves %l6 to THREAD_REG which is defined as %g7. In the
syscall case, the utl0() code then invokes the sycall_trap handler.
utl0, unless I'm mistaken, vectors to the TL0 trap table.
This is somewhat strange because in sun4u the kernel's %g7 isn't
the same as userland's %g7 (there are trap globals and other
globals)
Whole books could be written on sys_trap code flow. They probably would
not sell very well :-)
We're running unprivileged and at trap level 0 in userland and take some
trap, moving us on to another set of globals and traplevel (TL) 1.
Which set of globals we switch to depends on the trap - interrupt globals
for vector interrupts, alternate globals for most, mmu globals for mmu traps.
The PC changes to the corresponding entry in the TL0 trap table (trap_table0)
which begins the TL=1 handling of the trap. It may be that all handling
completes at TL > 0 (TL1 and any nested traps taken during that handling)
such as a simple TLB refill from the TSB or hash; or we may need to go
to C at TL0 to perform additional handling - to get back to C at TL0
the trap handler branches to sys_trap (eg for a pagefault).
sys_trap is used for that end goal from a variety of different contexts.
The caller of sys_trap can specify the C handler and a couple of arguments
in specifed registers.
sys_trap begins by inspecting %tstate to see if we were privileged at trap
time. In the case we were running in userland we're not and we go on
to label user_trap. The job of sys_trap is to get us back to TL0 for
further exception handling running in our own stack frame and register window
and with return linkage so we can get back to the trapped code.
In the case of user_trap obtaining a stack is easy - we just perform
a SAVE instruction on the kernel stack for this thread
(CPU->cpu_thread->t_stack);
and perform some jiggery-pokery on the "other" windows. We switch the
primary context to that of the kernel, and leave the secondary context
setup for quick ASI access to userland, and fall through to the
have_win label (shared by user and priv/prom trap code once a
window is obtained) with the CPU->cpu_thread (kernel thread pointer
for the user lwp that trapped) still in %g5 (priv/prom trap stores
something else here). user_trap sets %g6 to utl0 before dropping
into have_win - priv/prom traps set it to ktl0/ptl0; %g6 is
the PC we will continue executing at once have_win switches us
back to TL0.
have_win stashes the %g5 (thread pointer if user trap) in %l6. Up to now
we've been confined to using our trap globals, but we're about to
drop from TL1 to TL0 on globals as defined in TSTATE_KERN - the
regular globals (not interrupt/alternate/mmu). So we're going to
lose %g5 contents. But we now have our own register window,
so we own the locals so we use %l6. Note that at no time here
can we stand on the in or out registers until we preserve them
(which we do once back at TL0 and before calling the TL0 handler).
have_win returns us to utl0/ktl0/ptl0 by writing the requested
target to %tnpc and performing a DONE instruction (which takes you
down a trap level from 1 to 0 and resumes at %tnpc; note that
sys_trap forces TL1 on entry for anyone who branches to it from
TL > 1 which is also legal).
So now we're at utl0 running in state PSTATE_KERN - (regular globals,
interrupts disabled for now). We must jump to the requested C TL0
trap handler, but must first save state as it was at trap time -
globals and outs, for a user trap these are the user globals
and user outs in the register window of the trapped user code.
Before jmpl to the handler we write %l6 to THREAD_REG - %l6
is the kernel thread pointer we preserved back in user_trap as described
above. Once we have made THREAD_REG point correctly to the
kernel thread we can enable interrupts, as they must be before calling
the C handler. We could not allow interrupts up to now because the
interrupt handling code requires correct setting of THREAD_REG.
On return from the C handler we go through return-from-trap code,
user_rtt for user traps. After performing a bunch of work
and restoring of state this arranges for us to resume the original trapped
code.
Gavin
_______________________________________________
opensolaris-code mailing list
[email protected]
http://mail.opensolaris.org/mailman/listinfo/opensolaris-code