summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorPhilip Guenthe <guenther@cvs.openbsd.org>2012-06-21 00:57:00 +0000
committerPhilip Guenthe <guenther@cvs.openbsd.org>2012-06-21 00:57:00 +0000
commit867c8588faf5fba418fc7c3a85aa2bd4c3327e01 (patch)
treee98c388fcdff4a138a38722ee463c1b12f6c133a /sys/arch
parent28222fd1268ab97426703666e99f70ed942e847b (diff)
__tfork() needs to set the stack address of the new thread in the kernel,
so that it can't get a signal while still running on the parent thread's stack. Also, pass in sizeof(struct __tfork) to provide forward compat when more members are added. This is an ABI change, so switch syscall numbers and bump lib majors this time. ok deraadt@ matthew@
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/hppa/hppa/machdep.c41
-rw-r--r--sys/arch/hppa/hppa/vm_machdep.c4
-rw-r--r--sys/arch/hppa/include/frame.h7
-rw-r--r--sys/arch/hppa64/hppa64/machdep.c46
-rw-r--r--sys/arch/hppa64/hppa64/vm_machdep.c4
-rw-r--r--sys/arch/sparc/sparc/vm_machdep.c18
-rw-r--r--sys/arch/sparc64/sparc64/vm_machdep.c12
7 files changed, 82 insertions, 50 deletions
diff --git a/sys/arch/hppa/hppa/machdep.c b/sys/arch/hppa/hppa/machdep.c
index f38055b2363..2cc1d6ee24d 100644
--- a/sys/arch/hppa/hppa/machdep.c
+++ b/sys/arch/hppa/hppa/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.205 2011/09/20 09:49:38 miod Exp $ */
+/* $OpenBSD: machdep.c,v 1.206 2012/06/21 00:56:59 guenther Exp $ */
/*
* Copyright (c) 1999-2003 Michael Shalayeff
@@ -1133,6 +1133,25 @@ copyout(const void *src, void *dst, size_t size)
}
/*
+ * Set up tf_sp and tf_r3 (the frame pointer) and copy out the
+ * frame marker and the old r3
+ */
+int
+setstack(struct trapframe *tf, u_long stack, register_t old_r3)
+{
+ static const register_t zero = 0;
+ int err;
+
+ tf->tf_r3 = stack;
+ err = copyout(&old_r3, (caddr_t)stack, sizeof(register_t));
+
+ tf->tf_sp = stack += HPPA_FRAME_SIZE;
+ return (copyout(&zero, (caddr_t)(stack + HPPA_FRAME_CRP),
+ sizeof(register_t)) || err);
+}
+
+
+/*
* Set registers on exec.
*/
void
@@ -1141,7 +1160,6 @@ setregs(struct proc *p, struct exec_package *pack, u_long stack,
{
struct trapframe *tf = p->p_md.md_regs;
struct pcb *pcb = &p->p_addr->u_pcb;
- register_t zero;
tf->tf_flags = TFF_SYS|TFF_LAST;
tf->tf_iioq_tail = 4 +
@@ -1151,12 +1169,7 @@ setregs(struct proc *p, struct exec_package *pack, u_long stack,
tf->tf_arg1 = tf->tf_arg2 = 0; /* XXX dynload stuff */
/* setup terminal stack frame */
- stack = (stack + 0x1f) & ~0x1f;
- tf->tf_r3 = stack;
- tf->tf_sp = stack += HPPA_FRAME_SIZE;
- zero = 0;
- copyout(&zero, (caddr_t)(stack - HPPA_FRAME_SIZE), sizeof(register_t));
- copyout(&zero, (caddr_t)(stack + HPPA_FRAME_CRP), sizeof(register_t));
+ setstack(tf, (stack + 0x1f) & ~0x1f, 0);
/* reset any of the pending FPU exceptions */
fpu_proc_flush(p);
@@ -1261,12 +1274,13 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type,
bcopy(&p->p_addr->u_pcb.pcb_fpstate->hfp_regs, ksc.sc_fpregs,
sizeof(ksc.sc_fpregs));
- sss += HPPA_FRAME_SIZE;
+ if (setstack(tf, scp + sss, tf->tf_r3))
+ sigexit(p, SIGILL);
+
tf->tf_arg0 = sig;
tf->tf_arg1 = sip;
tf->tf_arg2 = tf->tf_r4 = scp;
tf->tf_arg3 = (register_t)catcher;
- tf->tf_sp = scp + sss;
tf->tf_ipsw &= ~(PSL_N|PSL_B|PSL_T);
tf->tf_iioq_head = HPPA_PC_PRIV_USER | p->p_sigcode;
tf->tf_iioq_tail = tf->tf_iioq_head + 4;
@@ -1276,7 +1290,7 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type,
#ifdef DEBUG
if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
printf("sendsig(%d): sig %d scp %p fp %p sp 0x%x\n",
- p->p_pid, sig, scp, ksc.sc_fp, (register_t)scp + sss);
+ p->p_pid, sig, scp, ksc.sc_fp, tf->tf_sp);
#endif
if (copyout(&ksc, (void *)scp, sizeof(ksc)))
@@ -1288,11 +1302,6 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type,
sigexit(p, SIGILL);
}
- if (copyout(&tf->tf_r3, (caddr_t)(tf->tf_sp - HPPA_FRAME_SIZE),
- sizeof(register_t)))
- sigexit(p, SIGILL);
- tf->tf_r3 = tf->tf_sp - HPPA_FRAME_SIZE;
-
#ifdef DEBUG
if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
printf("sendsig(%d): pc 0x%x catcher 0x%x\n", p->p_pid,
diff --git a/sys/arch/hppa/hppa/vm_machdep.c b/sys/arch/hppa/hppa/vm_machdep.c
index 3d6154beebf..9642cf0da5b 100644
--- a/sys/arch/hppa/hppa/vm_machdep.c
+++ b/sys/arch/hppa/hppa/vm_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vm_machdep.c,v 1.75 2011/09/20 21:46:08 miod Exp $ */
+/* $OpenBSD: vm_machdep.c,v 1.76 2012/06/21 00:56:59 guenther Exp $ */
/*
* Copyright (c) 1999-2004 Michael Shalayeff
@@ -147,7 +147,7 @@ cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize,
* If specified, give the child a different stack.
*/
if (stack != NULL)
- tf->tf_sp = (register_t)stack;
+ setstack(tf, (u_long)stack, 0); /* XXX ignore error? */
/*
* Build stack frames for the cpu_switchto & co.
diff --git a/sys/arch/hppa/include/frame.h b/sys/arch/hppa/include/frame.h
index 09b289e476f..28810732471 100644
--- a/sys/arch/hppa/include/frame.h
+++ b/sys/arch/hppa/include/frame.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: frame.h,v 1.18 2011/11/14 14:29:53 deraadt Exp $ */
+/* $OpenBSD: frame.h,v 1.19 2012/06/21 00:56:59 guenther Exp $ */
/*
* Copyright (c) 1999-2004 Michael Shalayeff
@@ -135,6 +135,11 @@ struct trapframe {
unsigned long tf_pad[3]; /* pad to 256 bytes */
};
+
+#ifdef _KERNEL
+int setstack(struct trapframe *, u_long, register_t);
+#endif /* _KERNEL */
+
#endif /* !_LOCORE */
#endif /* !_MACHINE_FRAME_H_ */
diff --git a/sys/arch/hppa64/hppa64/machdep.c b/sys/arch/hppa64/hppa64/machdep.c
index 8634c3e40a0..f701dddc6a7 100644
--- a/sys/arch/hppa64/hppa64/machdep.c
+++ b/sys/arch/hppa64/hppa64/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.45 2011/09/22 21:48:34 jsing Exp $ */
+/* $OpenBSD: machdep.c,v 1.46 2012/06/21 00:56:59 guenther Exp $ */
/*
* Copyright (c) 2005 Michael Shalayeff
@@ -777,6 +777,26 @@ copyout(const void *src, void *dst, size_t size)
}
/*
+ * Set up tf_sp and tf_r3 (the frame pointer) and copy out the
+ * frame marker and the old r3.
+ * XXX old_r3 is always zero on hppa64? It's non-zero on hppa in sendsig()
+ * XXX Set up tf_ret1 (aka "ap") too?
+ */
+int
+setstack(struct trapframe *tf, u_long stack, register_t old_r3)
+{
+ static const register_t zero = 0;
+ int err;
+
+ tf->tf_r3 = stack;
+ err = copyout(&old_r3, (caddr_t)stack, sizeof(register_t));
+
+ tf->tf_sp = stack += HPPA_FRAME_SIZE;
+ return (copyout(&zero, (caddr_t)(stack + HPPA_FRAME_CRP),
+ sizeof(register_t)) || err);
+}
+
+/*
* Set registers on exec.
*/
void
@@ -785,7 +805,6 @@ setregs(struct proc *p, struct exec_package *pack, u_long stack,
{
struct trapframe *tf = p->p_md.md_regs;
struct pcb *pcb = &p->p_addr->u_pcb;
- register_t zero;
tf->tf_flags = TFF_SYS|TFF_LAST;
tf->tf_iioq[1] = 4 +
@@ -795,13 +814,8 @@ setregs(struct proc *p, struct exec_package *pack, u_long stack,
tf->tf_args[1] = tf->tf_args[2] = 0; /* XXX dynload stuff */
/* setup terminal stack frame */
- stack = (stack + 0x1f) & ~0x1f;
- tf->tf_r3 = stack;
- tf->tf_sp = stack += HPPA_FRAME_SIZE;
- tf->tf_ret1 = stack - 16; /* ap */
- zero = 0;
- copyout(&zero, (caddr_t)(stack - HPPA_FRAME_SIZE), sizeof(register_t));
- copyout(&zero, (caddr_t)(stack + HPPA_FRAME_RP), sizeof(register_t));
+ setstack(tf, (stack + 0x1f) & ~0x1f, 0);
+ tf->tf_ret1 = tf->tf_sp - 16; /* ap */
/* reset any of the pending FPU exceptions */
fpu_proc_flush(p);
@@ -827,7 +841,7 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type,
struct sigacts *psp = p->p_sigacts;
struct sigcontext ksc;
siginfo_t ksi;
- register_t scp, sip, zero;
+ register_t scp, sip;
int sss;
#ifdef DEBUG
@@ -874,12 +888,13 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type,
bcopy(&p->p_addr->u_pcb.pcb_fpstate->hfp_regs, ksc.sc_fpregs,
sizeof(ksc.sc_fpregs));
- sss += HPPA_FRAME_SIZE;
+ if (setstack(tf, scp + sss, 0))
+ sigexit(p, SIGILL);
+
tf->tf_args[0] = sig;
tf->tf_args[1] = sip;
tf->tf_args[2] = tf->tf_r4 = scp;
tf->tf_args[3] = (register_t)catcher;
- tf->tf_sp = scp + sss;
tf->tf_ipsw &= ~(PSL_N|PSL_B|PSL_T);
tf->tf_iioq[0] = HPPA_PC_PRIV_USER | p->p_sigcode;
tf->tf_iioq[1] = tf->tf_iioq[0] + 4;
@@ -889,7 +904,7 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type,
#ifdef DEBUG
if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
printf("sendsig(%d): sig %d scp %p fp %p sp 0x%x\n",
- p->p_pid, sig, scp, ksc.sc_fp, (register_t)scp + sss);
+ p->p_pid, sig, scp, ksc.sc_fp, tf->tf_sp);
#endif
if (copyout(&ksc, (void *)scp, sizeof(ksc)))
@@ -901,11 +916,6 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type,
sigexit(p, SIGILL);
}
- zero = 0;
- if (copyout(&zero, (caddr_t)scp + sss - HPPA_FRAME_SIZE,
- sizeof(register_t)))
- sigexit(p, SIGILL);
-
#ifdef DEBUG
if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
printf("sendsig(%d): pc 0x%x, catcher 0x%x\n", p->p_pid,
diff --git a/sys/arch/hppa64/hppa64/vm_machdep.c b/sys/arch/hppa64/hppa64/vm_machdep.c
index e0ab2e49822..2facb90e8c3 100644
--- a/sys/arch/hppa64/hppa64/vm_machdep.c
+++ b/sys/arch/hppa64/hppa64/vm_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vm_machdep.c,v 1.17 2011/09/22 13:50:30 deraadt Exp $ */
+/* $OpenBSD: vm_machdep.c,v 1.18 2012/06/21 00:56:59 guenther Exp $ */
/*
* Copyright (c) 2005 Michael Shalayeff
@@ -136,7 +136,7 @@ cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize,
* If specified, give the child a different stack.
*/
if (stack != NULL)
- tf->tf_sp = (register_t)stack;
+ setstack(tf, (u_long)stack, 0); /* XXX ignore error? */
/*
* Build stack frames for the cpu_switchto & co.
diff --git a/sys/arch/sparc/sparc/vm_machdep.c b/sys/arch/sparc/sparc/vm_machdep.c
index 80b24f37955..8f28e16bd3f 100644
--- a/sys/arch/sparc/sparc/vm_machdep.c
+++ b/sys/arch/sparc/sparc/vm_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vm_machdep.c,v 1.54 2011/04/07 15:30:16 miod Exp $ */
+/* $OpenBSD: vm_machdep.c,v 1.55 2012/06/21 00:56:59 guenther Exp $ */
/* $NetBSD: vm_machdep.c,v 1.30 1997/03/10 23:55:40 pk Exp $ */
/*
@@ -407,12 +407,6 @@ cpu_fork(p1, p2, stack, stacksize, func, arg)
/* Copy parent's trapframe */
*tf2 = *(struct trapframe *)((int)opcb + USPACE - sizeof(*tf2));
- /*
- * If specified, give the child a different stack.
- */
- if (stack != NULL)
- tf2->tf_out[6] = (u_int)stack + stacksize;
-
/* Duplicate efforts of syscall(), but slightly differently */
if (tf2->tf_global[1] & SYSCALL_G2RFLAG) {
/* jmp %g2 (or %g7, deprecated) on success */
@@ -439,6 +433,16 @@ cpu_fork(p1, p2, stack, stacksize, func, arg)
rp->rw_local[0] = (int)func; /* Function to call */
rp->rw_local[1] = (int)arg; /* and its argument */
+ /*
+ * If specified, give the child a different stack, with space
+ * reserved for the frame, and zero the frame pointer.
+ */
+ if (stack != NULL) {
+ tf2->tf_out[6] = (u_int)stack + stacksize
+ - sizeof(struct frame);
+ rp->rw_in[6] = 0;
+ }
+
npcb->pcb_pc = (int)proc_trampoline - 8;
npcb->pcb_sp = (int)rp;
npcb->pcb_psr &= ~PSR_CWP; /* Run in window #0 */
diff --git a/sys/arch/sparc64/sparc64/vm_machdep.c b/sys/arch/sparc64/sparc64/vm_machdep.c
index 0e7b07d4c20..c3a454f3d30 100644
--- a/sys/arch/sparc64/sparc64/vm_machdep.c
+++ b/sys/arch/sparc64/sparc64/vm_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vm_machdep.c,v 1.27 2011/01/13 21:19:42 kettenis Exp $ */
+/* $OpenBSD: vm_machdep.c,v 1.28 2012/06/21 00:56:59 guenther Exp $ */
/* $NetBSD: vm_machdep.c,v 1.38 2001/06/30 00:02:20 eeh Exp $ */
/*
@@ -241,10 +241,14 @@ cpu_fork(p1, p2, stack, stacksize, func, arg)
*tf2 = *(struct trapframe *)((long)opcb + USPACE - sizeof(*tf2));
/*
- * If specified, give the child a different stack.
+ * If specified, give the child a different stack, offset and
+ * with space reserved for the frame, and zero the frame pointer.
*/
- if (stack != NULL)
- tf2->tf_out[6] = (u_int64_t)(u_long)stack + stacksize;
+ if (stack != NULL) {
+ tf2->tf_out[6] = (u_int64_t)(u_long)stack + stacksize
+ - (BIAS + CC64FSZ);
+ tf2->tf_in[6] = 0;
+ }
/* Duplicate efforts of syscall(), but slightly differently */
if (tf2->tf_global[1] & SYSCALL_G2RFLAG) {