Align the symbol that demarks the end of the signal code on a 16 byte

boundary.  It must be on at least an 8 byte boundary so that the length
of the signal code is a multiple of 8 (well aligned).  The size is used
in the calculation of the address of the argument and environment vectors
on the user stack; getting it wrong results in the string pointers being
misaligned and causes alignment faults in getenv() among other things.

Allocate a regular stack frame below the signal frame on the user stack
and join up the frame pointer to the previous frame.  This fixes longjmp-ing
out of signal handlers.  Longjmp traverses the stack upwards in order to
find the right frame to return to, so the frame pointers must join up
seamlessly.  I thought this would just work, but obviously the frame
needs to be below the signal frame, not above it like before.  Account
for the extra space in the signal code.

Preload pointers to interrupt data structures in interrupt globals.
This avoids the need to load the pointers from memory in the vectored
interrupt trap handler.

Transfer the first 2 out registers into td_retval in setregs.  We use
the same registers for system call arguments as return values, so these
registers got clobbered by the system call return values on return from
execve.  They now get clobbered by the right values.  We must put the values
in both the out registers in the trapframe and in td_retval because init
calls exec but fails to transfer the return value into the out registers.
This fixes a bug where the first exec after init would pass junk to the
c runtime, instead of a pointer to the argument strings.  A better solution
would be to return EJUSTRETURN on success from execve.

Adjust for change in pmap_bootstraps prototype.

Map the message buffer after the trap table is setup.  We will fault
on it immediately.
This commit is contained in:
Jake Burkholder 2001-10-20 16:36:08 +00:00
parent 6ef2d9a02d
commit 2baa1ef450
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=85242
3 changed files with 32 additions and 15 deletions

View File

@ -62,13 +62,14 @@ END(_start)
ENTRY(sigcode)
call %o4
nop
add %sp, SPOFF + SF_UC, %o0
add %sp, SPOFF + CCFSZ + SF_UC, %o0
mov SYS_sigreturn, %g1
ta %xcc, 9
mov SYS_exit, %g1
ta %xcc, 9
1: b %xcc, 1b
nop
.align 16
esigcode:
END(sigcode)

View File

@ -62,13 +62,14 @@ END(_start)
ENTRY(sigcode)
call %o4
nop
add %sp, SPOFF + SF_UC, %o0
add %sp, SPOFF + CCFSZ + SF_UC, %o0
mov SYS_sigreturn, %g1
ta %xcc, 9
mov SYS_exit, %g1
ta %xcc, 9
1: b %xcc, 1b
nop
.align 16
esigcode:
END(sigcode)

View File

@ -41,6 +41,7 @@
*/
#include "opt_ddb.h"
#include "opt_msgbuf.h"
#include <sys/param.h>
#include <sys/systm.h>
@ -48,9 +49,11 @@
#include <sys/kernel.h>
#include <sys/linker.h>
#include <sys/lock.h>
#include <sys/msgbuf.h>
#include <sys/mutex.h>
#include <sys/pcpu.h>
#include <sys/proc.h>
#include <sys/reboot.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/bus.h>
@ -178,6 +181,7 @@ tick_get_timecount(struct timecounter *tc)
void
sparc64_init(struct bootinfo *bi, ofw_vec_t *vec)
{
vm_offset_t off;
u_long ps;
/*
@ -197,6 +201,8 @@ sparc64_init(struct bootinfo *bi, ofw_vec_t *vec)
panic("sparc64_init: bootinfo version mismatch");
if (bi->bi_metadata == 0)
panic("sparc64_init: no loader metadata");
boothowto = bi->bi_howto;
kern_envp = (char *)bi->bi_envp;
preload_metadata = (caddr_t)bi->bi_metadata;
/*
@ -211,7 +217,7 @@ sparc64_init(struct bootinfo *bi, ofw_vec_t *vec)
/*
* Initialize virtual memory.
*/
pmap_bootstrap(bi->bi_kpa, bi->bi_end);
pmap_bootstrap(bi->bi_end);
/*
* Disable tick for now.
@ -224,6 +230,13 @@ sparc64_init(struct bootinfo *bi, ofw_vec_t *vec)
wrpr(tl, 0, 1);
wrpr(tba, tl0_base, 0);
/*
* Map and initialize the message buffer (after setting trap table).
*/
for (off = 0; off < round_page(MSGBUF_SIZE); off += PAGE_SIZE)
pmap_kenter((vm_offset_t)msgbufp + off, msgbuf_phys + off);
msgbufinit(msgbufp, MSGBUF_SIZE);
proc_linkup(&proc0);
/*
* Initialize proc0 stuff (p_contested needs to be done early).
@ -236,6 +249,7 @@ sparc64_init(struct bootinfo *bi, ofw_vec_t *vec)
thread0->td_kstack = proc0kstack;
thread0->td_pcb = (struct pcb *)
(thread0->td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1;
frame0.tf_tstate = TSTATE_IE;
thread0->td_frame = &frame0;
LIST_INIT(&thread0->td_contested);
@ -244,12 +258,6 @@ sparc64_init(struct bootinfo *bi, ofw_vec_t *vec)
*/
globalp = &__globaldata;
/*
* Setup pointers to interrupt data tables.
*/
globalp->gd_iq = &intr_queues[0]; /* XXX cpuno */
globalp->gd_ivt = intr_vectors;
/*
* Put the globaldata pointer in the alternate and interrupt %g7 also.
* globaldata is tied to %g7. We could therefore also use assignments to
@ -264,7 +272,8 @@ sparc64_init(struct bootinfo *bi, ofw_vec_t *vec)
(&__globaldata.gd_alt_stack[ALT_STACK_SIZE - 1]));
__asm __volatile("mov %0, %%g7" : : "r" (&__globaldata));
wrpr(pstate, ps, PSTATE_IG);
__asm __volatile("mov %0, %%g7" : : "r" (&__globaldata));
__asm __volatile("mov %0, %%g6" : : "r" (&__globaldata.gd_iq));
__asm __volatile("mov %0, %%g7" : : "r" (&intr_vectors));
wrpr(pstate, ps, 0);
/*
@ -299,9 +308,10 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
struct sigacts *psp;
struct sigframe sf;
struct thread *td;
struct frame *fp;
struct proc *p;
u_long sp;
int oonstack;
u_long sp;
oonstack = 0;
td = curthread;
@ -346,8 +356,9 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
* and the stack can not be grown.
* useracc() will return FALSE if access is denied.
*/
if (vm_map_growstack(p, (u_long)sfp) != KERN_SUCCESS ||
!useracc((caddr_t)sfp, sizeof(*sfp), VM_PROT_WRITE)) {
fp = (struct frame *)sfp - 1;
if (vm_map_growstack(p, (u_long)fp) != KERN_SUCCESS ||
!useracc((caddr_t)fp, sizeof(*fp) + sizeof(*sfp), VM_PROT_WRITE)) {
/*
* Process has trashed its stack; give it an illegal
* instruction to halt it in its tracks.
@ -387,7 +398,8 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
PROC_UNLOCK(p);
/* Copy the sigframe out to the user's stack. */
if (rwindow_save(td) != 0 || copyout(&sf, sfp, sizeof(*sfp)) != 0) {
if (rwindow_save(td) != 0 || copyout(&sf, sfp, sizeof(*sfp)) != 0 ||
suword(&fp->f_in[6], tf->tf_out[6]) != 0) {
/*
* Something is wrong with the stack pointer.
* ...Kill the process.
@ -400,7 +412,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
tf->tf_tpc = PS_STRINGS - *(p->p_sysent->sv_szsigcode);
tf->tf_tnpc = tf->tf_tpc + 4;
tf->tf_sp = (u_long)sfp - SPOFF;
tf->tf_sp = (u_long)fp - SPOFF;
CTR3(KTR_SIG, "sendsig: return td=%p pc=%#lx sp=%#lx", td, tf->tf_tpc,
tf->tf_sp);
@ -499,6 +511,7 @@ setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
pcb = td->td_pcb;
/* XXX: honor the real number of windows... */
bzero(pcb->pcb_rw, sizeof(pcb->pcb_rw));
pcb->pcb_nsaved = 0;
/* The inital window for the process (%cw = 0). */
fp = (struct frame *)(td->td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1;
/* Make sure the frames that are frobbed are actually flushed. */
@ -528,6 +541,8 @@ setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
td->td_frame->tf_out[2] = 0;
td->td_frame->tf_out[3] = PS_STRINGS;
td->td_frame->tf_out[6] = sp - SPOFF - sizeof(struct frame);
td->td_retval[0] = td->td_frame->tf_out[0];
td->td_retval[1] = td->td_frame->tf_out[1];
wr(y, 0, 0);
mtx_unlock_spin(&sched_lock);
}