Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/compat/linux/arch/mips Deal with differences in signal d...



details:   https://anonhg.NetBSD.org/src/rev/f81f2009ec26
branches:  trunk
changeset: 762379:f81f2009ec26
user:      matt <matt%NetBSD.org@localhost>
date:      Sun Feb 20 08:14:10 2011 +0000

description:
Deal with differences in signal delivery between o32/n32/n64.

diffstat:

 sys/compat/linux/arch/mips/linux_machdep.c |  202 ++++++++++++++++++----------
 sys/compat/linux/arch/mips/linux_machdep.h |  134 +++++++++++++-----
 2 files changed, 224 insertions(+), 112 deletions(-)

diffs (truncated from 518 to 300 lines):

diff -r e9aca3afcfdf -r f81f2009ec26 sys/compat/linux/arch/mips/linux_machdep.c
--- a/sys/compat/linux/arch/mips/linux_machdep.c        Sun Feb 20 08:13:29 2011 +0000
+++ b/sys/compat/linux/arch/mips/linux_machdep.c        Sun Feb 20 08:14:10 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: linux_machdep.c,v 1.41 2010/07/07 01:30:34 chs Exp $ */
+/*     $NetBSD: linux_machdep.c,v 1.42 2011/02/20 08:14:10 matt Exp $ */
 
 /*-
  * Copyright (c) 1995, 2000, 2001 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.41 2010/07/07 01:30:34 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.42 2011/02/20 08:14:10 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -77,6 +77,13 @@
 
 #include <mips/cache.h>
 
+union linux_ksigframe {
+       struct linux_sigframe sf;
+#if !defined(__mips_o32)
+       struct linux_sigframe32 sf32;
+#endif
+};
+
 /*
  * To see whether wscons is configured (for virtual console ioctl calls).
  */
@@ -98,6 +105,32 @@
        return;
 }
 
+#if !defined(__mips_o32)
+static void
+linux_setup_sigcontext32(struct linux_sigcontext32 *sc,
+     const struct trapframe *tf)
+{
+       for (u_int i = 0; i < 32; i++) {
+               sc->lsc_regs[i] = tf->tf_regs[i];
+       }
+       sc->lsc_mdhi = tf->tf_regs[_R_MULHI];
+       sc->lsc_mdlo = tf->tf_regs[_R_MULLO];
+       sc->lsc_pc = tf->tf_regs[_R_PC];
+}
+#endif
+
+static void
+linux_setup_sigcontext(struct linux_sigcontext *sc,
+     const struct trapframe *tf)
+{
+       for (u_int i = 0; i < 32; i++) {
+               sc->lsc_regs[i] = tf->tf_regs[i];
+       }
+       sc->lsc_mdhi = tf->tf_regs[_R_MULHI];
+       sc->lsc_mdlo = tf->tf_regs[_R_MULLO];
+       sc->lsc_pc = tf->tf_regs[_R_PC];
+}
+
 /*
  * Send an interrupt to process.
  *
@@ -111,65 +144,66 @@
 linux_sendsig(const ksiginfo_t *ksi, const sigset_t *mask)
 {
        const int sig = ksi->ksi_signo;
-       struct lwp *l = curlwp;
-       struct proc *p = l->l_proc;
-       struct linux_sigframe *fp;
-       struct frame *f;
-       int i, onstack, error;
+       struct lwp * const l = curlwp;
+       struct proc * const p = l->l_proc;
+       struct trapframe * const tf = l->l_md.md_utf;
+#ifdef __mips_o32
+       const int abi = _MIPS_BSD_API_O32;
+#else
+       const int abi = p->p_md.md_abi;
+#endif
+       union linux_ksigframe ksf, *sf;
+       bool onstack;
+       int error;
        sig_t catcher = SIGACTION(p, sig).sa_handler;
-       struct linux_sigframe sf;
 
 #ifdef DEBUG_LINUX
        printf("linux_sendsig()\n");
 #endif /* DEBUG_LINUX */
-       f = (struct frame *)l->l_md.md_regs;
 
        /*
         * 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;
+       onstack = (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0
+           && (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;
 
        /*
         * Signal stack is broken (see at the end of linux_sigreturn), so we do
         * not use it yet. XXX fix this.
         */
-       onstack=0;
+       onstack = false;
 
        /*
         * Allocate space for the signal handler context.
         */
-       if (onstack)
-               fp = (struct linux_sigframe *)
-                   ((uintptr_t)l->l_sigstk.ss_sp
-                   + l->l_sigstk.ss_size);
-       else
-               /* cast for O64 ABI case */
-               fp = (struct linux_sigframe *)(uintptr_t)f->f_regs[_R_SP];
+       sf = (void *)(onstack
+           ? (uintptr_t) l->l_sigstk.ss_sp + l->l_sigstk.ss_size
+           : (uintptr_t) tf->tf_regs[_R_SP]);
 
        /*
         * Build stack frame for signal trampoline.
         */
-       memset(&sf, 0, sizeof sf);
+       memset(&ksf, 0, sizeof ksf);
 
        /*
         * This is the signal trampoline used by Linux, we don't use it,
         * but we set it up in case an application expects it to be there
         */
-       sf.lsf_code[0] = 0x24020000;    /* li   v0, __NR_sigreturn      */
-       sf.lsf_code[1] = 0x0000000c;    /* syscall                      */
+       ksf.sf.lsf_code[0] = 0x24020000; /* li  v0, __NR_sigreturn      */
+       ksf.sf.lsf_code[1] = 0x0000000c; /* syscall                     */
 
-       native_to_linux_sigset(&sf.lsf_mask, mask);
-       for (i=0; i<32; i++) {
-               sf.lsf_sc.lsc_regs[i] = f->f_regs[i];
+       switch (abi) {
+       default:
+               native_to_linux_sigset(&ksf.sf.lsf_mask, mask);
+               linux_setup_sigcontext(&ksf.sf.lsf_sc, tf);
+               break;
+#if !defined(__mips_o32)
+       case _MIPS_BSD_API_O32:
+               native_to_linux_sigset(&ksf.sf32.lsf_mask, mask);
+               linux_setup_sigcontext32(&ksf.sf32.lsf_sc, tf);
+               break;
+#endif
        }
-       sf.lsf_sc.lsc_mdhi = f->f_regs[_R_MULHI];
-       sf.lsf_sc.lsc_mdlo = f->f_regs[_R_MULLO];
-       sf.lsf_sc.lsc_pc = f->f_regs[_R_PC];
-       sf.lsf_sc.lsc_status = f->f_regs[_R_SR];
-       sf.lsf_sc.lsc_cause = f->f_regs[_R_CAUSE];
-       sf.lsf_sc.lsc_badvaddr = f->f_regs[_R_BADVADDR];
        sendsig_reset(l, sig);
 
        /*
@@ -180,9 +214,9 @@
        /*
         * Install the sigframe onto the stack
         */
-       fp -= sizeof(struct linux_sigframe);
+       sf -= sizeof(*sf);
        mutex_exit(p->p_lock);
-       error = copyout(&sf, fp, sizeof(sf));
+       error = copyout(&ksf, sf, sizeof(ksf));
        mutex_enter(p->p_lock);
 
        if (error != 0) {
@@ -198,19 +232,19 @@
        }
 
        /* Set up the registers to return to sigcode. */
-       f->f_regs[_R_A0] = native_to_linux_signo[sig];
-       f->f_regs[_R_A1] = 0;
-       f->f_regs[_R_A2] = (unsigned long)&fp->lsf_sc;
+       tf->tf_regs[_R_A0] = native_to_linux_signo[sig];
+       tf->tf_regs[_R_A1] = 0;
+       tf->tf_regs[_R_A2] = (intptr_t)&sf->sf.lsf_sc;
 
 #ifdef DEBUG_LINUX
-       printf("sigcontext is at %p\n", &fp->lsf_sc);
+       printf("sigcontext is at %p\n", &sf->sf.lsf_sc);
 #endif /* DEBUG_LINUX */
 
-       f->f_regs[_R_SP] = (unsigned long)fp;
+       tf->tf_regs[_R_SP] = (intptr_t)sf;
        /* Signal trampoline code is at base of user stack. */
-       f->f_regs[_R_RA] = (unsigned long)p->p_sigctx.ps_sigcode;
-       f->f_regs[_R_T9] = (unsigned long)catcher;
-       f->f_regs[_R_PC] = (unsigned long)catcher;
+       tf->tf_regs[_R_RA] = (intptr_t)p->p_sigctx.ps_sigcode;
+       tf->tf_regs[_R_T9] = (intptr_t)catcher;
+       tf->tf_regs[_R_PC] = (intptr_t)catcher;
 
        /* Remember that we're now on the signal stack. */
        if (onstack)
@@ -219,6 +253,32 @@
        return;
 }
 
+static void
+linux_putaway_sigcontext(struct trapframe *tf,
+    const struct linux_sigcontext *sc)
+{
+       for (u_int i = 0; i < 32; i++) {
+               tf->tf_regs[i] = sc->lsc_regs[i];
+       }
+       tf->tf_regs[_R_MULLO] = sc->lsc_mdlo;
+       tf->tf_regs[_R_MULHI] = sc->lsc_mdhi;
+       tf->tf_regs[_R_PC] = sc->lsc_pc;
+}
+
+#ifndef __mips_o32
+static void
+linux_putaway_sigcontext32(struct trapframe *tf,
+    const struct linux_sigcontext32 *sc)
+{
+       for (u_int i = 0; i < 32; i++) {
+               tf->tf_regs[i] = sc->lsc_regs[i];
+       }
+       tf->tf_regs[_R_MULLO] = sc->lsc_mdlo;
+       tf->tf_regs[_R_MULHI] = sc->lsc_mdhi;
+       tf->tf_regs[_R_PC] = sc->lsc_pc;
+}
+#endif
+
 /*
  * System call to cleanup state after a signal
  * has been taken.  Reset signal mask and
@@ -231,10 +291,15 @@
                syscallarg(struct linux_sigframe *) sf;
        } */
        struct proc *p = l->l_proc;
-       struct linux_sigframe *sf, ksf;
-       struct frame *f;
+       union linux_ksigframe ksf, *sf;
+#ifdef __mips_o32
+       const int abi = _MIPS_BSD_API_O32;
+#else
+       const int abi = p->p_md.md_abi;
+#endif
+       linux_sigset_t *lmask;
        sigset_t mask;
-       int i, error;
+       int error;
 
 #ifdef DEBUG_LINUX
        printf("linux_sys_sigreturn()\n");
@@ -245,20 +310,24 @@
         * It is unsafe to keep track of it ourselves, in the event that a
         * program jumps out of a signal handler.
         */
-       sf = SCARG(uap, sf);
+       sf = (void *)SCARG(uap, sf);
 
        if ((error = copyin(sf, &ksf, sizeof(ksf))) != 0)
                return (error);
 
        /* Restore the register context. */
-       f = (struct frame *)l->l_md.md_regs;
-       for (i=0; i<32; i++)
-               f->f_regs[i] = ksf.lsf_sc.lsc_regs[i];
-       f->f_regs[_R_MULLO] = ksf.lsf_sc.lsc_mdlo;
-       f->f_regs[_R_MULHI] = ksf.lsf_sc.lsc_mdhi;
-       f->f_regs[_R_PC] = ksf.lsf_sc.lsc_pc;
-       f->f_regs[_R_BADVADDR] = ksf.lsf_sc.lsc_badvaddr;
-       f->f_regs[_R_CAUSE] = ksf.lsf_sc.lsc_cause;
+       switch (abi) {
+       default:
+               lmask = &ksf.sf.lsf_mask;
+               linux_putaway_sigcontext(l->l_md.md_utf, &ksf.sf.lsf_sc);
+               break;
+#if !defined(__mips_o32)
+       case _MIPS_BSD_API_O32:
+               lmask = &ksf.sf32.lsf_mask;
+               linux_putaway_sigcontext32(l->l_md.md_utf, &ksf.sf32.lsf_sc);
+               break;
+#endif
+       }
 
        mutex_enter(p->p_lock);
 
@@ -266,7 +335,7 @@
        l->l_sigstk.ss_flags &= ~SS_ONSTACK;
 
        /* Restore signal mask. */
-       linux_to_native_sigset(&mask, (linux_sigset_t *)&ksf.lsf_mask);
+       linux_to_native_sigset(&mask, lmask);
        (void)sigprocmask1(l, SIG_SETMASK, &mask, 0);
 
        mutex_exit(p->p_lock);
@@ -282,21 +351,6 @@
 }
 



Home | Main Index | Thread Index | Old Index