Subject: proposal for PR 27023
To: None <tech-kern@netbsd.org, port-sparc@netbsd.org,>
From: Chuck Silvers <chuq@chuq.com>
List: port-sparc64
Date: 01/25/2005 09:38:01
hi,

here are my thoughts on PR 27023.  the problem is that SA context switches
on both sparc and sparc64 need to write the contents of the register windows
out to the user stack.  on a normal, non-SA context switch, if the stack
isn't valid (perhaps because it was paged out), we'd just write the
register windows to the PCB and go on.  this isn't good enough for SAs
though, since the PCB is tied to a particular kernel LWP and the user
thread may be run on a different LWP next.  so we really do need to get
the register window contents back to the real user stack.

the trouble is that by the time we try to write to the user stack, we're
already in the middle of going to sleep, and if we take a page-fault in
this context we can end up recursing into the context-switching code,
which is obviously non-sensical.

there are already several cases where the SA context-switching code can't
do everything it needs to do to achieve a real SA context switch, so it
just gives up and does a non-SA context switch instead.  I think we should
have this new sparc case do the same thing.  the best way I've thought of
to achieve this is to have the page-fault handler (mem_access_fault() on
sparc, data_access_fault() on sparc64) recognize that the fault is one
where we can't sleep, have it just fail instead of calling uvm_fault().
"fail" in this case would be to return to the pcb_onfault address, and
we would require that pcb_onfault be set in this case.  this would result
in the copyout() in rwindow_save() returning some distinctive error code
and returning that to cpu_getmcontext().  cpu_getmcontext() would
recognize that and return it back up through a couple more functions
to sa_switch(), which would take the error path from its call to
sa_upcall0() and do a non-SA mi_switch().

we'll need a flag somewhere to indicate to the page-fault handler code
that we're in this special case.  there are a bunch of LWP flags for SAs
already, but I'm guessing that none of them a really appropriate for
this case, so probably the best thing would be to add a pcb_flags field
to the PCB of both sparc platforms.

I can't think of any similar problem on another platform, so keeping this
sparc{,64} specific seems best.

comments?  if there are no objections I'll go ahead and implement the above.

-Chuck