summaryrefslogtreecommitdiffstats
path: root/sys/sparc64
diff options
context:
space:
mode:
authorjake <jake@FreeBSD.org>2001-10-20 16:36:08 +0000
committerjake <jake@FreeBSD.org>2001-10-20 16:36:08 +0000
commit1d421d0a011283f6fee1b65df0a0a0254e25a6ff (patch)
tree5ddfddbd66e68aef96a82e51a26bbb910912bb64 /sys/sparc64
parent0241151d04105fdb3adfe1f72aeaffe935bca98c (diff)
downloadFreeBSD-src-1d421d0a011283f6fee1b65df0a0a0254e25a6ff.zip
FreeBSD-src-1d421d0a011283f6fee1b65df0a0a0254e25a6ff.tar.gz
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.
Diffstat (limited to 'sys/sparc64')
-rw-r--r--sys/sparc64/sparc64/locore.S3
-rw-r--r--sys/sparc64/sparc64/locore.s3
-rw-r--r--sys/sparc64/sparc64/machdep.c41
3 files changed, 32 insertions, 15 deletions
diff --git a/sys/sparc64/sparc64/locore.S b/sys/sparc64/sparc64/locore.S
index a007fef..576e66c 100644
--- a/sys/sparc64/sparc64/locore.S
+++ b/sys/sparc64/sparc64/locore.S
@@ -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)
diff --git a/sys/sparc64/sparc64/locore.s b/sys/sparc64/sparc64/locore.s
index a007fef..576e66c 100644
--- a/sys/sparc64/sparc64/locore.s
+++ b/sys/sparc64/sparc64/locore.s
@@ -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)
diff --git a/sys/sparc64/sparc64/machdep.c b/sys/sparc64/sparc64/machdep.c
index 3c4d881..c422ba5 100644
--- a/sys/sparc64/sparc64/machdep.c
+++ b/sys/sparc64/sparc64/machdep.c
@@ -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);
@@ -245,12 +259,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
* globaldata here.
@@ -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);
}
OpenPOWER on IntegriCloud