Module Name:    src
Committed By:   reinoud
Date:           Sat Dec 24 12:26:58 UTC 2011

Modified Files:
        src/sys/arch/usermode/usermode: machdep.c

Log Message:
Make signals work for NetBSD/usermode[i386] !


To generate a diff of this commit:
cvs rdiff -u -r1.41 -r1.42 src/sys/arch/usermode/usermode/machdep.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/usermode/usermode/machdep.c
diff -u src/sys/arch/usermode/usermode/machdep.c:1.41 src/sys/arch/usermode/usermode/machdep.c:1.42
--- src/sys/arch/usermode/usermode/machdep.c:1.41	Tue Dec 20 22:48:59 2011
+++ src/sys/arch/usermode/usermode/machdep.c	Sat Dec 24 12:26:58 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: machdep.c,v 1.41 2011/12/20 22:48:59 jmcneill Exp $ */
+/* $NetBSD: machdep.c,v 1.42 2011/12/24 12:26:58 reinoud Exp $ */
 
 /*-
  * Copyright (c) 2011 Reinoud Zandijk <rein...@netbsd.org>
@@ -27,11 +27,18 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+/*
+ * Note that this machdep.c uses the `dummy' mcontext_t defined for usermode.
+ * This is basicly a blob of PAGE_SIZE big. We might want to switch over to
+ * non-generic mcontext_t's one day, but will this break non-NetBSD hosts?
+ */
+
+
 #include "opt_memsize.h"
 #include "opt_sdl.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.41 2011/12/20 22:48:59 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.42 2011/12/24 12:26:58 reinoud Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -141,22 +148,6 @@ consinit(void)
 	printf("NetBSD/usermode startup\n");
 }
 
-void
-sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask)
-{
-#if 1
-	printf("%s: ", __func__);
-	printf("flags %d, ", (int) ksi->ksi_flags);
-	printf("to lwp %d, signo %d, code %d, errno %d\n",
-		(int) ksi->ksi_lid,
-		ksi->ksi_signo,
-		ksi->ksi_code,
-		ksi->ksi_errno);
-#endif
-
-	panic("%s not implemented", __func__);
-}
-
 int
 mm_md_physacc(paddr_t pa, vm_prot_t prog)
 {
@@ -184,6 +175,108 @@ dump_regs(register_t *reg)
 }
 #endif
 
+
+/* from sys/arch/i386/include/frame.h : KEEP IN SYNC */
+
+/*
+ * New-style signal frame
+ */
+struct sigframe_siginfo {
+	int		sf_ra;		/* return address for handler */
+	int		sf_signum;	/* "signum" argument for handler */
+	siginfo_t	*sf_sip;	/* "sip" argument for handler */
+	ucontext_t	*sf_ucp;	/* "ucp" argument for handler */
+	siginfo_t	sf_si;		/* actual saved siginfo */
+	ucontext_t	sf_uc;		/* actual saved ucontext */
+};
+
+
+/*
+ * mcontext extensions to handle signal delivery.
+ */
+#define _UC_SETSTACK	0x00010000
+#define _UC_CLRSTACK	0x00020000
+#define _UC_VM		0x00040000
+#define	_UC_TLSBASE	0x00080000
+
+
+void
+sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask)
+{
+	struct lwp *l = curlwp;
+	struct proc *p = l->l_proc;
+	struct pcb *pcb = lwp_getpcb(l);
+	struct sigacts *ps = p->p_sigacts;
+	struct sigframe_siginfo *fp, frame;
+	int sig = ksi->ksi_signo;
+	sig_t catcher = SIGACTION(p, sig).sa_handler;
+	ucontext_t *ucp = &pcb->pcb_userret_ucp;
+	register_t *reg = (register_t *) &ucp->uc_mcontext;
+	int onstack, error;
+
+	KASSERT(mutex_owned(p->p_lock));
+
+#if 0
+	printf("%s: ", __func__);
+	printf("flags %d, ", (int) ksi->ksi_flags);
+	printf("to lwp %d, signo %d, code %d, errno %d\n",
+		(int) ksi->ksi_lid,
+		ksi->ksi_signo,
+		ksi->ksi_code,
+		ksi->ksi_errno);
+#endif
+
+	/* do we need to jump onto the signal stack? */
+	onstack = (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0
+	    && (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;
+
+	fp = (void *) reg[17];	/* ESP */
+	if (onstack)
+		fp = (void *)
+			((char *) l->l_sigstk.ss_sp + l->l_sigstk.ss_size);
+
+	fp--;
+
+	/* set up stack frame */
+	frame.sf_ra = (int)ps->sa_sigdesc[sig].sd_tramp;
+	frame.sf_signum = sig;
+	frame.sf_sip = &fp->sf_si;
+	frame.sf_ucp = &fp->sf_uc;
+	frame.sf_si._info = ksi->ksi_info;
+
+	/* copy our userret context into sf_uc */
+	memcpy(&frame.sf_uc, ucp, sizeof(ucontext_t));
+	frame.sf_uc.uc_sigmask = *mask;
+	frame.sf_uc.uc_link = l->l_ctxlink; /* XXX ??? */
+	frame.sf_uc.uc_flags |= (l->l_sigstk.ss_flags & SS_ONSTACK)
+	    ? _UC_SETSTACK : _UC_CLRSTACK;
+	memset(&frame.sf_uc.uc_stack, 0, sizeof(frame.sf_uc.uc_stack));
+
+	sendsig_reset(l, sig);
+
+	/* copyout our frame to the stackframe */
+	mutex_exit(p->p_lock);
+	error = copyout(&frame, fp, sizeof(frame));
+	mutex_enter(p->p_lock);
+
+	if (error != 0) {
+		/*
+		 * Process has trashed its stack; give it an illegal
+		 * instruction to halt it in its tracks.
+		 */
+		sigexit(l, SIGILL);
+		/* NOTREACHED */
+	}
+
+	/* set catcher and the new stack pointer */
+	reg[17] = (register_t) fp;	/* ESP */
+	reg[14] = (register_t) catcher;	/* EIP */
+
+	/* Remember that we're now on the signal stack. */
+	if (onstack)
+		l->l_sigstk.ss_flags |= SS_ONSTACK;
+}
+
 void
 setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack)
 {
@@ -298,7 +391,7 @@ md_syscall_get_opcode(ucontext_t *ucp, u
 {
 	register_t *reg = (register_t *) &ucp->uc_mcontext;
 //	uint8_t  *p8  = (uint8_t *) (reg[14]);
-	uint16_t *p16 = (uint16_t*) (reg[14]);
+	uint16_t *p16 = (uint16_t*) (reg[14]);	/* EIP */
 
 	switch (*p16) {
 	case 0xff0f:	/* UD1      */

Reply via email to