summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2020-06-24 20:49:12 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2020-06-24 20:49:12 +0000
commitd5d00fdfec2707a72d8f409ed3069c27bc916b04 (patch)
tree6e113aea644ecbc5e4fcf117ed3899783883bead /sys/arch
parentc1a61024fa8b5c0f578e03bb6b121a4276350c09 (diff)
First stab at making signal handling work.
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/powerpc64/include/frame.h9
-rw-r--r--sys/arch/powerpc64/powerpc64/locore.S8
-rw-r--r--sys/arch/powerpc64/powerpc64/machdep.c111
3 files changed, 120 insertions, 8 deletions
diff --git a/sys/arch/powerpc64/include/frame.h b/sys/arch/powerpc64/include/frame.h
index 7cadf7e48c9..350817de180 100644
--- a/sys/arch/powerpc64/include/frame.h
+++ b/sys/arch/powerpc64/include/frame.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: frame.h,v 1.3 2020/06/14 17:56:54 kettenis Exp $ */
+/* $OpenBSD: frame.h,v 1.4 2020/06/24 20:49:11 kettenis Exp $ */
/*
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
@@ -46,6 +46,13 @@ struct callframe {
register_t cf_toc;
};
+struct sigframe {
+ int sf_signum;
+ siginfo_t *sf_sip;
+ struct sigcontext sf_sc;
+ siginfo_t sf_si;
+};
+
struct switchframe {
register_t sf_sp;
register_t sf_cr;
diff --git a/sys/arch/powerpc64/powerpc64/locore.S b/sys/arch/powerpc64/powerpc64/locore.S
index 505623037ee..8e56e4401d4 100644
--- a/sys/arch/powerpc64/powerpc64/locore.S
+++ b/sys/arch/powerpc64/powerpc64/locore.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.S,v 1.18 2020/06/22 18:49:36 kettenis Exp $ */
+/* $OpenBSD: locore.S,v 1.19 2020/06/24 20:49:11 kettenis Exp $ */
/*
* Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
@@ -18,6 +18,8 @@
#include "assym.h"
+#include <sys/syscall.h>
+
#include <machine/opal.h>
#include <machine/psl.h>
@@ -28,6 +30,10 @@
.globl sigcode
.globl sigcoderet
sigcode:
+ mtctr %r12
+ bctrl
+ li %r0, SYS_sigreturn
+ sc
sigcoderet:
blr
.globl esigcode
diff --git a/sys/arch/powerpc64/powerpc64/machdep.c b/sys/arch/powerpc64/powerpc64/machdep.c
index b06d55de12c..c7783f178eb 100644
--- a/sys/arch/powerpc64/powerpc64/machdep.c
+++ b/sys/arch/powerpc64/powerpc64/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.29 2020/06/22 16:09:33 kettenis Exp $ */
+/* $OpenBSD: machdep.c,v 1.30 2020/06/24 20:49:11 kettenis Exp $ */
/*
* Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
@@ -17,13 +17,16 @@
*/
#include <sys/param.h>
-#include <sys/systm.h>
#include <sys/buf.h>
#include <sys/exec.h>
#include <sys/exec_elf.h>
+#include <sys/mount.h>
#include <sys/msgbuf.h>
#include <sys/proc.h>
#include <sys/reboot.h>
+#include <sys/signalvar.h>
+#include <sys/syscallargs.h>
+#include <sys/systm.h>
#include <sys/user.h>
#include <machine/cpufunc.h>
@@ -601,6 +604,9 @@ parse_bootargs(const char *bootargs)
}
}
+#define PSL_USER \
+ (PSL_SF | PSL_HV | PSL_EE | PSL_PR | PSL_ME | PSL_IR | PSL_DR | PSL_RI)
+
void
setregs(struct proc *p, struct exec_package *pack, u_long stack,
register_t *retval)
@@ -609,8 +615,7 @@ setregs(struct proc *p, struct exec_package *pack, u_long stack,
frame->fixreg[1] = stack;
frame->srr0 = pack->ep_entry;
- frame->srr1 = PSL_SF | PSL_HV | PSL_EE | PSL_PR | PSL_ME |
- PSL_IR | PSL_DR | PSL_RI;
+ frame->srr1 = PSL_USER;
retval[1] = 0;
}
@@ -618,13 +623,107 @@ setregs(struct proc *p, struct exec_package *pack, u_long stack,
void
sendsig(sig_t catcher, int sig, sigset_t mask, const siginfo_t *ksip)
{
- printf("%s\n", __func__);
+ struct proc *p = curproc;
+ struct trapframe *tf = p->p_md.md_regs;
+ struct sigframe *fp, frame;
+ struct sigacts *psp = p->p_p->ps_sigacts;
+ siginfo_t *sip = NULL;
+ int i;
+
+ /* Allocate space for the signal handler context. */
+ if ((p->p_sigstk.ss_flags & SS_DISABLE) == 0 &&
+ !sigonstack(tf->fixreg[1]) && (psp->ps_sigonstack & sigmask(sig)))
+ fp = (struct sigframe *)
+ trunc_page((vaddr_t)p->p_sigstk.ss_sp + p->p_sigstk.ss_size);
+ else
+ fp = (struct sigframe *)tf->fixreg[1];
+
+ fp = (struct sigframe *)(STACKALIGN(fp - 1) - 288);
+
+ /* Build stack frame for signal trampoline. */
+ memset(&frame, 0, sizeof(frame));
+ frame.sf_signum = sig;
+
+ /* Save register context. */
+ for (i = 0; i < 32; i++)
+ frame.sf_sc.sc_frame.fixreg[i] = tf->fixreg[i];
+ frame.sf_sc.sc_frame.lr = tf->lr;
+ frame.sf_sc.sc_frame.cr = tf->cr;
+ frame.sf_sc.sc_frame.xer = tf->xer;
+ frame.sf_sc.sc_frame.ctr = tf->ctr;
+ frame.sf_sc.sc_frame.srr0 = tf->srr0;
+ frame.sf_sc.sc_frame.srr1 = tf->srr1;
+
+ /* Save signal mask. */
+ frame.sf_sc.sc_mask = mask;
+
+ if (psp->ps_siginfo & sigmask(sig)) {
+ sip = &fp->sf_si;
+ frame.sf_si = *ksip;
+ }
+
+ frame.sf_sc.sc_cookie = (long)&fp->sf_sc ^ p->p_p->ps_sigcookie;
+ if (copyout(&frame, fp, sizeof(frame)))
+ sigexit(p, SIGILL);
+
+ /*
+ * Build context to run handler in.
+ */
+ tf->fixreg[1] = (register_t)fp;
+ tf->fixreg[3] = sig;
+ tf->fixreg[4] = (register_t)sip;
+ tf->fixreg[5] = (register_t)&fp->sf_sc;
+ tf->fixreg[12] = (register_t)catcher;
+
+ tf->srr0 = p->p_p->ps_sigcode;
}
int
sys_sigreturn(struct proc *p, void *v, register_t *retval)
{
- printf("%s\n", __func__);
+ struct sys_sigreturn_args /* {
+ syscallarg(struct sigcontext *) sigcntxp;
+ } */ *uap = v;
+ struct sigcontext ksc, *scp = SCARG(uap, sigcntxp);
+ struct trapframe *tf = p->p_md.md_regs;
+ int error;
+ int i;
+
+ if (PROC_PC(p) != p->p_p->ps_sigcoderet) {
+ sigexit(p, SIGILL);
+ return EPERM;
+ }
+
+ if ((error = copyin(scp, &ksc, sizeof ksc)))
+ return error;
+
+ if (ksc.sc_cookie != ((long)scp ^ p->p_p->ps_sigcookie)) {
+ sigexit(p, SIGILL);
+ return EFAULT;
+ }
+
+ /* Prevent reuse of the sigcontext cookie */
+ ksc.sc_cookie = 0;
+ (void)copyout(&ksc.sc_cookie, (caddr_t)scp +
+ offsetof(struct sigcontext, sc_cookie), sizeof (ksc.sc_cookie));
+
+ /* Make sure the processor mode has not been tampered with. */
+ if (ksc.sc_frame.srr1 != PSL_USER)
+ return EINVAL;
+
+ /* Restore register context. */
+ for (i = 0; i < 32; i++)
+ tf->fixreg[i] = ksc.sc_frame.fixreg[i];
+ tf->lr = ksc.sc_frame.lr;
+ tf->cr = ksc.sc_frame.cr;
+ tf->xer = ksc.sc_frame.xer;
+ tf->ctr = ksc.sc_frame.ctr;
+ tf->srr0 = ksc.sc_frame.srr0;
+ tf->srr1 = ksc.sc_frame.srr1;
+
+ /* Restore signal mask. */
+ p->p_sigmask = ksc.sc_mask & ~sigcantmask;
+
return EJUSTRETURN;
}