OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [m68k/] [kernel/] [signal.c] - Diff between revs 1765 and 1782

Only display areas with differences | Details | Blame | View Log

Rev 1765 Rev 1782
/*
/*
 *  linux/arch/m68k/kernel/signal.c
 *  linux/arch/m68k/kernel/signal.c
 *
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file COPYING in the main directory of this archive
 * License.  See the file COPYING in the main directory of this archive
 * for more details.
 * for more details.
 */
 */
 
 
/*
/*
 * 680x0 support by Hamish Macdonald
 * 680x0 support by Hamish Macdonald
 */
 */
 
 
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/mm.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/signal.h>
#include <linux/errno.h>
#include <linux/errno.h>
#include <linux/wait.h>
#include <linux/wait.h>
#include <linux/ptrace.h>
#include <linux/ptrace.h>
#include <linux/unistd.h>
#include <linux/unistd.h>
 
 
#include <asm/segment.h>
#include <asm/segment.h>
#include <asm/pgtable.h>
#include <asm/pgtable.h>
#include <asm/traps.h>
#include <asm/traps.h>
#include <asm/bootinfo.h>
#include <asm/bootinfo.h>
 
 
#define offsetof(type, member)  ((size_t)(&((type *)0)->member))
#define offsetof(type, member)  ((size_t)(&((type *)0)->member))
 
 
#define _S(nr) (1<<((nr)-1))
#define _S(nr) (1<<((nr)-1))
 
 
#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
 
 
asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
asmlinkage int do_signal(unsigned long oldmask, struct pt_regs *regs);
asmlinkage int do_signal(unsigned long oldmask, struct pt_regs *regs);
 
 
static const int extra_sizes[16] = {
static const int extra_sizes[16] = {
  0,
  0,
  -1, /* sizeof(((struct frame *)0)->un.fmt1), */
  -1, /* sizeof(((struct frame *)0)->un.fmt1), */
  sizeof(((struct frame *)0)->un.fmt2),
  sizeof(((struct frame *)0)->un.fmt2),
  sizeof(((struct frame *)0)->un.fmt3),
  sizeof(((struct frame *)0)->un.fmt3),
  sizeof(((struct frame *)0)->un.fmt4),
  sizeof(((struct frame *)0)->un.fmt4),
  -1, /* sizeof(((struct frame *)0)->un.fmt5), */
  -1, /* sizeof(((struct frame *)0)->un.fmt5), */
  -1, /* sizeof(((struct frame *)0)->un.fmt6), */
  -1, /* sizeof(((struct frame *)0)->un.fmt6), */
  sizeof(((struct frame *)0)->un.fmt7),
  sizeof(((struct frame *)0)->un.fmt7),
  -1, /* sizeof(((struct frame *)0)->un.fmt8), */
  -1, /* sizeof(((struct frame *)0)->un.fmt8), */
  sizeof(((struct frame *)0)->un.fmt9),
  sizeof(((struct frame *)0)->un.fmt9),
  sizeof(((struct frame *)0)->un.fmta),
  sizeof(((struct frame *)0)->un.fmta),
  sizeof(((struct frame *)0)->un.fmtb),
  sizeof(((struct frame *)0)->un.fmtb),
  -1, /* sizeof(((struct frame *)0)->un.fmtc), */
  -1, /* sizeof(((struct frame *)0)->un.fmtc), */
  -1, /* sizeof(((struct frame *)0)->un.fmtd), */
  -1, /* sizeof(((struct frame *)0)->un.fmtd), */
  -1, /* sizeof(((struct frame *)0)->un.fmte), */
  -1, /* sizeof(((struct frame *)0)->un.fmte), */
  -1, /* sizeof(((struct frame *)0)->un.fmtf), */
  -1, /* sizeof(((struct frame *)0)->un.fmtf), */
};
};
 
 
/*
/*
 * atomically swap in the new signal mask, and wait for a signal.
 * atomically swap in the new signal mask, and wait for a signal.
 */
 */
asmlinkage int do_sigsuspend(struct pt_regs *regs)
asmlinkage int do_sigsuspend(struct pt_regs *regs)
{
{
        unsigned long oldmask = current->blocked;
        unsigned long oldmask = current->blocked;
        unsigned long newmask = regs->d3;
        unsigned long newmask = regs->d3;
 
 
        current->blocked = newmask & _BLOCKABLE;
        current->blocked = newmask & _BLOCKABLE;
        regs->d0 = -EINTR;
        regs->d0 = -EINTR;
        while (1) {
        while (1) {
                current->state = TASK_INTERRUPTIBLE;
                current->state = TASK_INTERRUPTIBLE;
                schedule();
                schedule();
                if (do_signal(oldmask, regs))
                if (do_signal(oldmask, regs))
                        return -EINTR;
                        return -EINTR;
        }
        }
}
}
 
 
static unsigned char fpu_version = 0;    /* version number of fpu, set by setup_frame */
static unsigned char fpu_version = 0;    /* version number of fpu, set by setup_frame */
 
 
/*
/*
 * This sets regs->usp even though we don't actually use sigstacks yet..
 * This sets regs->usp even though we don't actually use sigstacks yet..
 */
 */
asmlinkage int do_sigreturn(unsigned long __unused)
asmlinkage int do_sigreturn(unsigned long __unused)
{
{
        struct sigcontext_struct context;
        struct sigcontext_struct context;
        struct frame * regs;
        struct frame * regs;
        struct switch_stack *sw;
        struct switch_stack *sw;
        int fsize = 0;
        int fsize = 0;
        int formatvec = 0;
        int formatvec = 0;
        unsigned long fp;
        unsigned long fp;
        unsigned long usp = rdusp();
        unsigned long usp = rdusp();
 
 
#if 0
#if 0
        printk("sys_sigreturn, usp=%08x\n", (unsigned) usp);
        printk("sys_sigreturn, usp=%08x\n", (unsigned) usp);
#endif
#endif
 
 
        /* get stack frame pointer */
        /* get stack frame pointer */
        sw = (struct switch_stack *) &__unused;
        sw = (struct switch_stack *) &__unused;
        regs = (struct frame *) (sw + 1);
        regs = (struct frame *) (sw + 1);
 
 
        /* get previous context (including pointer to possible extra junk) */
        /* get previous context (including pointer to possible extra junk) */
        if (verify_area(VERIFY_READ, (void *)usp, sizeof(context)))
        if (verify_area(VERIFY_READ, (void *)usp, sizeof(context)))
                goto badframe;
                goto badframe;
 
 
        memcpy_fromfs(&context,(void *)usp, sizeof(context));
        memcpy_fromfs(&context,(void *)usp, sizeof(context));
 
 
        fp = usp + sizeof (context);
        fp = usp + sizeof (context);
 
 
        /* restore signal mask */
        /* restore signal mask */
        current->blocked = context.sc_mask & _BLOCKABLE;
        current->blocked = context.sc_mask & _BLOCKABLE;
 
 
        /* restore passed registers */
        /* restore passed registers */
        regs->ptregs.d0 = context.sc_d0;
        regs->ptregs.d0 = context.sc_d0;
        regs->ptregs.d1 = context.sc_d1;
        regs->ptregs.d1 = context.sc_d1;
        regs->ptregs.a0 = context.sc_a0;
        regs->ptregs.a0 = context.sc_a0;
        regs->ptregs.a1 = context.sc_a1;
        regs->ptregs.a1 = context.sc_a1;
        regs->ptregs.sr = (regs->ptregs.sr & 0xff00)|(context.sc_sr & 0xff);
        regs->ptregs.sr = (regs->ptregs.sr & 0xff00)|(context.sc_sr & 0xff);
        regs->ptregs.pc = context.sc_pc;
        regs->ptregs.pc = context.sc_pc;
 
 
        wrusp(context.sc_usp);
        wrusp(context.sc_usp);
        formatvec = context.sc_formatvec;
        formatvec = context.sc_formatvec;
        regs->ptregs.format = formatvec >> 12;
        regs->ptregs.format = formatvec >> 12;
        regs->ptregs.vector = formatvec & 0xfff;
        regs->ptregs.vector = formatvec & 0xfff;
        if (context.sc_fpstate[0])
        if (context.sc_fpstate[0])
          {
          {
            /* Verify the frame format.  */
            /* Verify the frame format.  */
            if (context.sc_fpstate[0] != fpu_version){
            if (context.sc_fpstate[0] != fpu_version){
#if DEBUG
#if DEBUG
            printk("fpregs=%08x fpcntl=%08x\n", context.sc_fpregs,
            printk("fpregs=%08x fpcntl=%08x\n", context.sc_fpregs,
                   context.sc_fpcntl);
                   context.sc_fpcntl);
            printk("Wrong fpu: sc_fpstate[0]=%02x fpu_version=%02x\n",
            printk("Wrong fpu: sc_fpstate[0]=%02x fpu_version=%02x\n",
                   (unsigned) context.sc_fpstate[0], (unsigned) fpu_version);
                   (unsigned) context.sc_fpstate[0], (unsigned) fpu_version);
            {
            {
              int i;
              int i;
              printk("Saved fp_state: ");
              printk("Saved fp_state: ");
              for (i = 0; i < 216; i++){
              for (i = 0; i < 216; i++){
                printk("%02x ", context.sc_fpstate[i]);
                printk("%02x ", context.sc_fpstate[i]);
              }
              }
              printk("\n");
              printk("\n");
            }
            }
#endif
#endif
              goto badframe;
              goto badframe;
            }
            }
            if (boot_info.cputype & FPU_68881)
            if (boot_info.cputype & FPU_68881)
              {
              {
                if (context.sc_fpstate[1] != 0x18
                if (context.sc_fpstate[1] != 0x18
                    && context.sc_fpstate[1] != 0xb4)
                    && context.sc_fpstate[1] != 0xb4)
                  goto badframe;
                  goto badframe;
              }
              }
            else if (boot_info.cputype & FPU_68882)
            else if (boot_info.cputype & FPU_68882)
              {
              {
                if (context.sc_fpstate[1] != 0x38
                if (context.sc_fpstate[1] != 0x38
                    && context.sc_fpstate[1] != 0xd4){
                    && context.sc_fpstate[1] != 0xd4){
#if 0
#if 0
                  printk("Wrong 68882 fpu-state\n");
                  printk("Wrong 68882 fpu-state\n");
#endif
#endif
                  goto badframe;
                  goto badframe;
                }
                }
              }
              }
            else if (boot_info.cputype & FPU_68040)
            else if (boot_info.cputype & FPU_68040)
              {
              {
                if (!((context.sc_fpstate[1] == 0x00)|| \
                if (!((context.sc_fpstate[1] == 0x00)|| \
                      (context.sc_fpstate[1] == 0x28)|| \
                      (context.sc_fpstate[1] == 0x28)|| \
                      (context.sc_fpstate[1] == 0x60))){
                      (context.sc_fpstate[1] == 0x60))){
#if 0
#if 0
                  printk("Wrong 68040 fpu-state\n");
                  printk("Wrong 68040 fpu-state\n");
#endif
#endif
                  goto badframe;
                  goto badframe;
                }
                }
              }
              }
            else if (boot_info.cputype & FPU_68060)
            else if (boot_info.cputype & FPU_68060)
              {
              {
                if (!((context.sc_fpstate[1] == 0x00)|| \
                if (!((context.sc_fpstate[1] == 0x00)|| \
                      (context.sc_fpstate[1] == 0x60)|| \
                      (context.sc_fpstate[1] == 0x60)|| \
                      (context.sc_fpstate[1] == 0xe0))){
                      (context.sc_fpstate[1] == 0xe0))){
#if 0
#if 0
                  printk("Wrong 68060 fpu-state\n");
                  printk("Wrong 68060 fpu-state\n");
#endif
#endif
                  goto badframe;
                  goto badframe;
                }
                }
              }
              }
            __asm__ volatile ("fmovemx %0,%/fp0-%/fp1\n\t"
            __asm__ volatile ("fmovemx %0,%/fp0-%/fp1\n\t"
                              "fmoveml %1,%/fpcr/%/fpsr/%/fpiar"
                              "fmoveml %1,%/fpcr/%/fpsr/%/fpiar"
                              : /* no outputs */
                              : /* no outputs */
                              : "m" (*context.sc_fpregs),
                              : "m" (*context.sc_fpregs),
                                "m" (*context.sc_fpcntl));
                                "m" (*context.sc_fpcntl));
          }
          }
        __asm__ volatile ("frestore %0" : : "m" (*context.sc_fpstate));
        __asm__ volatile ("frestore %0" : : "m" (*context.sc_fpstate));
 
 
        fsize = extra_sizes[regs->ptregs.format];
        fsize = extra_sizes[regs->ptregs.format];
        if (fsize < 0) {
        if (fsize < 0) {
                /*
                /*
                 * user process trying to return with weird frame format
                 * user process trying to return with weird frame format
                 */
                 */
#if DEBUG
#if DEBUG
              printk("user process returning with weird frame format\n");
              printk("user process returning with weird frame format\n");
#endif
#endif
                goto badframe;
                goto badframe;
        }
        }
 
 
        /* OK.  Make room on the supervisor stack for the extra junk,
        /* OK.  Make room on the supervisor stack for the extra junk,
         * if necessary.
         * if necessary.
         */
         */
 
 
        if (fsize) {
        if (fsize) {
                if (verify_area(VERIFY_READ, (void *)fp, fsize))
                if (verify_area(VERIFY_READ, (void *)fp, fsize))
                        goto badframe;
                        goto badframe;
 
 
#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
                __asm__ __volatile__
                __asm__ __volatile__
                        ("movel %0,%/a0\n\t"
                        ("movel %0,%/a0\n\t"
                         "subl %1,%/a0\n\t"     /* make room on stack */
                         "subl %1,%/a0\n\t"     /* make room on stack */
                         "movel %/a0,%/sp\n\t"  /* set stack pointer */
                         "movel %/a0,%/sp\n\t"  /* set stack pointer */
                         /* move switch_stack and pt_regs */
                         /* move switch_stack and pt_regs */
                         "1: movel %0@+,%/a0@+\n\t"
                         "1: movel %0@+,%/a0@+\n\t"
                         "   dbra %2,1b\n\t"
                         "   dbra %2,1b\n\t"
                         "lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt stuff */
                         "lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt stuff */
                         "lsrl  #2,%1\n\t"
                         "lsrl  #2,%1\n\t"
                         "subql #1,%1\n\t"
                         "subql #1,%1\n\t"
                         "2: movesl %4@+,%2\n\t"
                         "2: movesl %4@+,%2\n\t"
                         "   movel %2,%/a0@+\n\t"
                         "   movel %2,%/a0@+\n\t"
                         "   dbra %1,2b\n\t"
                         "   dbra %1,2b\n\t"
                         "bral " SYMBOL_NAME_STR(ret_from_signal)
                         "bral " SYMBOL_NAME_STR(ret_from_signal)
                         : /* no outputs, it doesn't ever return */
                         : /* no outputs, it doesn't ever return */
                         : "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
                         : "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
                           "n" (frame_offset), "a" (fp)
                           "n" (frame_offset), "a" (fp)
                         : "a0");
                         : "a0");
#undef frame_offset
#undef frame_offset
                goto badframe;
                goto badframe;
                /* NOTREACHED */
                /* NOTREACHED */
        }
        }
 
 
        return regs->ptregs.d0;
        return regs->ptregs.d0;
badframe:
badframe:
        do_exit(SIGSEGV);
        do_exit(SIGSEGV);
}
}
 
 
/*
/*
 * Set up a signal frame...
 * Set up a signal frame...
 *
 *
 * This routine is somewhat complicated by the fact that if the
 * This routine is somewhat complicated by the fact that if the
 * kernel may be entered by an exception other than a system call;
 * kernel may be entered by an exception other than a system call;
 * e.g. a bus error or other "bad" exception.  If this is the case,
 * e.g. a bus error or other "bad" exception.  If this is the case,
 * then *all* the context on the kernel stack frame must be saved.
 * then *all* the context on the kernel stack frame must be saved.
 *
 *
 * For a large number of exceptions, the stack frame format is the same
 * For a large number of exceptions, the stack frame format is the same
 * as that which will be created when the process traps back to the kernel
 * as that which will be created when the process traps back to the kernel
 * when finished executing the signal handler.  In this case, nothing
 * when finished executing the signal handler.  In this case, nothing
 * must be done.  This is exception frame format "0".  For exception frame
 * must be done.  This is exception frame format "0".  For exception frame
 * formats "2", "9", "A" and "B", the extra information on the frame must
 * formats "2", "9", "A" and "B", the extra information on the frame must
 * be saved.  This information is saved on the user stack and restored
 * be saved.  This information is saved on the user stack and restored
 * when the signal handler is returned.
 * when the signal handler is returned.
 *
 *
 * The format of the user stack when executing the signal handler is:
 * The format of the user stack when executing the signal handler is:
 *
 *
 *     usp ->  RETADDR (points to code below)
 *     usp ->  RETADDR (points to code below)
 *             signum  (parm #1)
 *             signum  (parm #1)
 *             sigcode (parm #2 ; vector number)
 *             sigcode (parm #2 ; vector number)
 *             scp     (parm #3 ; sigcontext pointer, pointer to #1 below)
 *             scp     (parm #3 ; sigcontext pointer, pointer to #1 below)
 *             code1   (addaw #20,sp) ; pop parms and code off stack
 *             code1   (addaw #20,sp) ; pop parms and code off stack
 *             code2   (moveq #119,d0; trap #0) ; sigreturn syscall
 *             code2   (moveq #119,d0; trap #0) ; sigreturn syscall
 *     #1|     oldmask
 *     #1|     oldmask
 *       |     old usp
 *       |     old usp
 *       |     d0      (first saved reg)
 *       |     d0      (first saved reg)
 *       |     d1
 *       |     d1
 *       |     a0
 *       |     a0
 *       |     a1
 *       |     a1
 *       |     sr      (saved status register)
 *       |     sr      (saved status register)
 *       |     pc      (old pc; one to return to)
 *       |     pc      (old pc; one to return to)
 *       |     forvec  (format and vector word of old supervisor stack frame)
 *       |     forvec  (format and vector word of old supervisor stack frame)
 *       |     floating point context
 *       |     floating point context
 *
 *
 * These are optionally followed by some extra stuff, depending on the
 * These are optionally followed by some extra stuff, depending on the
 * stack frame interrupted. This is 1 longword for format "2", 3
 * stack frame interrupted. This is 1 longword for format "2", 3
 * longwords for format "9", 6 longwords for format "A", and 21
 * longwords for format "9", 6 longwords for format "A", and 21
 * longwords for format "B".
 * longwords for format "B".
 */
 */
 
 
#define UFRAME_SIZE(fs) (sizeof(struct sigcontext_struct)/4 + 6 + fs/4)
#define UFRAME_SIZE(fs) (sizeof(struct sigcontext_struct)/4 + 6 + fs/4)
 
 
static void setup_frame (struct sigaction * sa, unsigned long **fp,
static void setup_frame (struct sigaction * sa, unsigned long **fp,
                         unsigned long pc, struct frame *regs, int
                         unsigned long pc, struct frame *regs, int
                         signr, unsigned long oldmask)
                         signr, unsigned long oldmask)
{
{
        struct sigcontext_struct context;
        struct sigcontext_struct context;
        unsigned long *frame, *tframe;
        unsigned long *frame, *tframe;
        int fsize = extra_sizes[regs->ptregs.format];
        int fsize = extra_sizes[regs->ptregs.format];
 
 
        if (fsize < 0) {
        if (fsize < 0) {
                printk ("setup_frame: Unknown frame format %#x\n",
                printk ("setup_frame: Unknown frame format %#x\n",
                        regs->ptregs.format);
                        regs->ptregs.format);
                do_exit(SIGSEGV);
                do_exit(SIGSEGV);
        }
        }
        frame = *fp - UFRAME_SIZE(fsize);
        frame = *fp - UFRAME_SIZE(fsize);
        if (verify_area(VERIFY_WRITE,frame,UFRAME_SIZE(fsize)*4))
        if (verify_area(VERIFY_WRITE,frame,UFRAME_SIZE(fsize)*4))
                do_exit(SIGSEGV);
                do_exit(SIGSEGV);
        if (fsize) {
        if (fsize) {
                memcpy_tofs (frame + UFRAME_SIZE(0), &regs->un, fsize);
                memcpy_tofs (frame + UFRAME_SIZE(0), &regs->un, fsize);
                regs->ptregs.stkadj = fsize;
                regs->ptregs.stkadj = fsize;
        }
        }
 
 
/* set up the "normal" stack seen by the signal handler */
/* set up the "normal" stack seen by the signal handler */
        tframe = frame;
        tframe = frame;
 
 
        /* return address points to code on stack */
        /* return address points to code on stack */
        put_user((ulong)(frame+4), tframe); tframe++;
        put_user((ulong)(frame+4), tframe); tframe++;
        if (current->exec_domain && current->exec_domain->signal_invmap)
        if (current->exec_domain && current->exec_domain->signal_invmap)
            put_user(current->exec_domain->signal_invmap[signr], tframe);
            put_user(current->exec_domain->signal_invmap[signr], tframe);
        else
        else
            put_user(signr, tframe);
            put_user(signr, tframe);
        tframe++;
        tframe++;
 
 
        put_user(regs->ptregs.vector, tframe); tframe++;
        put_user(regs->ptregs.vector, tframe); tframe++;
        /* "scp" parameter.  points to sigcontext */
        /* "scp" parameter.  points to sigcontext */
        put_user((ulong)(frame+6), tframe); tframe++;
        put_user((ulong)(frame+6), tframe); tframe++;
 
 
/* set up the return code... */
/* set up the return code... */
        put_user(0xdefc0014,tframe); tframe++; /* addaw #20,sp */
        put_user(0xdefc0014,tframe); tframe++; /* addaw #20,sp */
        put_user(0x70774e40,tframe); tframe++; /* moveq #119,d0; trap #0 */
        put_user(0x70774e40,tframe); tframe++; /* moveq #119,d0; trap #0 */
 
 
/* Flush caches so the instructions will be correctly executed. (MA) */
/* Flush caches so the instructions will be correctly executed. (MA) */
        cache_push_v ((unsigned long)frame, (int)tframe - (int)frame);
        cache_push_v ((unsigned long)frame, (int)tframe - (int)frame);
 
 
/* setup and copy the sigcontext structure */
/* setup and copy the sigcontext structure */
        context.sc_mask       = oldmask;
        context.sc_mask       = oldmask;
        context.sc_usp        = (unsigned long)*fp;
        context.sc_usp        = (unsigned long)*fp;
        context.sc_d0         = regs->ptregs.d0;
        context.sc_d0         = regs->ptregs.d0;
        context.sc_d1         = regs->ptregs.d1;
        context.sc_d1         = regs->ptregs.d1;
        context.sc_a0         = regs->ptregs.a0;
        context.sc_a0         = regs->ptregs.a0;
        context.sc_a1         = regs->ptregs.a1;
        context.sc_a1         = regs->ptregs.a1;
        context.sc_sr         = regs->ptregs.sr;
        context.sc_sr         = regs->ptregs.sr;
        context.sc_pc         = pc;
        context.sc_pc         = pc;
        context.sc_formatvec  = (regs->ptregs.format << 12 |
        context.sc_formatvec  = (regs->ptregs.format << 12 |
                                 regs->ptregs.vector);
                                 regs->ptregs.vector);
#if DEBUG
#if DEBUG
        printk("formatvec: %02x\n", (unsigned) context.sc_formatvec);
        printk("formatvec: %02x\n", (unsigned) context.sc_formatvec);
#endif
#endif
        __asm__ volatile ("fsave %0" : : "m" (*context.sc_fpstate) : "memory");
        __asm__ volatile ("fsave %0" : : "m" (*context.sc_fpstate) : "memory");
        if (context.sc_fpstate[0])
        if (context.sc_fpstate[0])
          {
          {
            fpu_version = context.sc_fpstate[0];
            fpu_version = context.sc_fpstate[0];
#if DEBUG
#if DEBUG
            {
            {
              int i;
              int i;
              printk("Saved fp_state: ");
              printk("Saved fp_state: ");
              for (i = 0; i < 216; i++){
              for (i = 0; i < 216; i++){
                printk("%02x ", context.sc_fpstate[i]);
                printk("%02x ", context.sc_fpstate[i]);
              }
              }
              printk("\n");
              printk("\n");
            }
            }
            printk("fpregs=%08x fpcntl=%08x\n", context.sc_fpregs,
            printk("fpregs=%08x fpcntl=%08x\n", context.sc_fpregs,
                   context.sc_fpcntl);
                   context.sc_fpcntl);
#endif
#endif
            __asm__ volatile ("fmovemx %/fp0-%/fp1,%0\n\t"
            __asm__ volatile ("fmovemx %/fp0-%/fp1,%0\n\t"
                              "fmoveml %/fpcr/%/fpsr/%/fpiar,%1"
                              "fmoveml %/fpcr/%/fpsr/%/fpiar,%1"
                              : /* no outputs */
                              : /* no outputs */
                              : "m" (*context.sc_fpregs),
                              : "m" (*context.sc_fpregs),
                                "m" (*context.sc_fpcntl)
                                "m" (*context.sc_fpcntl)
                              : "memory");
                              : "memory");
          }
          }
#if DEBUG
#if DEBUG
        {
        {
          int i;
          int i;
          printk("Saved fp_state: ");
          printk("Saved fp_state: ");
          for (i = 0; i < 216; i++){
          for (i = 0; i < 216; i++){
            printk("%02x ", context.sc_fpstate[i]);
            printk("%02x ", context.sc_fpstate[i]);
          }
          }
          printk("\n");
          printk("\n");
        }
        }
#endif
#endif
        memcpy_tofs (tframe, &context, sizeof(context));
        memcpy_tofs (tframe, &context, sizeof(context));
        /*
        /*
         * no matter what frame format we were using before, we
         * no matter what frame format we were using before, we
         * will do the "RTE" using a normal 4 word frame.
         * will do the "RTE" using a normal 4 word frame.
         */
         */
        regs->ptregs.format = 0;
        regs->ptregs.format = 0;
 
 
        /* "return" new usp to caller */
        /* "return" new usp to caller */
        *fp = frame;
        *fp = frame;
}
}
 
 
/*
/*
 * Note that 'init' is a special process: it doesn't get signals it doesn't
 * Note that 'init' is a special process: it doesn't get signals it doesn't
 * want to handle. Thus you cannot kill init even with a SIGKILL even by
 * want to handle. Thus you cannot kill init even with a SIGKILL even by
 * mistake.
 * mistake.
 *
 *
 * Note that we go through the signals twice: once to check the signals
 * Note that we go through the signals twice: once to check the signals
 * that the kernel can handle, and then we build all the user-level signal
 * that the kernel can handle, and then we build all the user-level signal
 * handling stack-frames in one go after that.
 * handling stack-frames in one go after that.
 */
 */
asmlinkage int do_signal(unsigned long oldmask, struct pt_regs *regs_in)
asmlinkage int do_signal(unsigned long oldmask, struct pt_regs *regs_in)
{
{
        unsigned long mask = ~current->blocked;
        unsigned long mask = ~current->blocked;
        unsigned long handler_signal = 0;
        unsigned long handler_signal = 0;
        unsigned long *frame = NULL;
        unsigned long *frame = NULL;
        unsigned long pc = 0;
        unsigned long pc = 0;
        unsigned long signr;
        unsigned long signr;
        struct frame *regs = (struct frame *)regs_in;
        struct frame *regs = (struct frame *)regs_in;
        struct sigaction * sa;
        struct sigaction * sa;
 
 
        current->tss.esp0 = (unsigned long) regs;
        current->tss.esp0 = (unsigned long) regs;
 
 
        while ((signr = current->signal & mask)) {
        while ((signr = current->signal & mask)) {
                __asm__("bfffo  %2,#0,#0,%1\n\t"
                __asm__("bfffo  %2,#0,#0,%1\n\t"
                        "bfclr  %0,%1,#1\n\t"
                        "bfclr  %0,%1,#1\n\t"
                        "eorw   #31,%1"
                        "eorw   #31,%1"
                        :"=m" (current->signal),"=r" (signr)
                        :"=m" (current->signal),"=r" (signr)
                        :"1" (signr));
                        :"1" (signr));
                sa = current->sig->action + signr;
                sa = current->sig->action + signr;
                signr++;
                signr++;
 
 
                if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
                if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
                        current->exit_code = signr;
                        current->exit_code = signr;
                        current->state = TASK_STOPPED;
                        current->state = TASK_STOPPED;
                        notify_parent(current);
                        notify_parent(current);
                        schedule();
                        schedule();
                        if (!(signr = current->exit_code)) {
                        if (!(signr = current->exit_code)) {
                        discard_frame:
                        discard_frame:
                                /* Make sure that a faulted bus cycle
                                /* Make sure that a faulted bus cycle
                                   isn't restarted.  */
                                   isn't restarted.  */
                                switch (regs->ptregs.format) {
                                switch (regs->ptregs.format) {
                                case 7:
                                case 7:
                                case 9:
                                case 9:
                                case 10:
                                case 10:
                                case 11:
                                case 11:
                                  regs->ptregs.stkadj = extra_sizes[regs->ptregs.format];
                                  regs->ptregs.stkadj = extra_sizes[regs->ptregs.format];
                                  regs->ptregs.format = 0;
                                  regs->ptregs.format = 0;
                                  break;
                                  break;
                                }
                                }
                                continue;
                                continue;
                        }
                        }
                        current->exit_code = 0;
                        current->exit_code = 0;
                        if (signr == SIGSTOP)
                        if (signr == SIGSTOP)
                                goto discard_frame;
                                goto discard_frame;
                        if (_S(signr) & current->blocked) {
                        if (_S(signr) & current->blocked) {
                                current->signal |= _S(signr);
                                current->signal |= _S(signr);
                                continue;
                                continue;
                        }
                        }
                        sa = current->sig->action + signr - 1;
                        sa = current->sig->action + signr - 1;
                }
                }
                if (sa->sa_handler == SIG_IGN) {
                if (sa->sa_handler == SIG_IGN) {
                        if (signr != SIGCHLD)
                        if (signr != SIGCHLD)
                                continue;
                                continue;
                        /* check for SIGCHLD: it's special */
                        /* check for SIGCHLD: it's special */
                        while (sys_waitpid(-1,NULL,WNOHANG) > 0)
                        while (sys_waitpid(-1,NULL,WNOHANG) > 0)
                                /* nothing */;
                                /* nothing */;
                        continue;
                        continue;
                }
                }
                if (sa->sa_handler == SIG_DFL) {
                if (sa->sa_handler == SIG_DFL) {
                        if (current->pid == 1)
                        if (current->pid == 1)
                                continue;
                                continue;
                        switch (signr) {
                        switch (signr) {
                            case SIGCONT: case SIGCHLD: case SIGWINCH:
                            case SIGCONT: case SIGCHLD: case SIGWINCH:
                                continue;
                                continue;
 
 
                            case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU:
                            case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU:
                                if (current->flags & PF_PTRACED)
                                if (current->flags & PF_PTRACED)
                                        continue;
                                        continue;
                                current->state = TASK_STOPPED;
                                current->state = TASK_STOPPED;
                                current->exit_code = signr;
                                current->exit_code = signr;
                                if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags &
                                if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags &
                                      SA_NOCLDSTOP))
                                      SA_NOCLDSTOP))
                                        notify_parent(current);
                                        notify_parent(current);
                                schedule();
                                schedule();
                                continue;
                                continue;
 
 
                            case SIGQUIT: case SIGILL: case SIGTRAP:
                            case SIGQUIT: case SIGILL: case SIGTRAP:
                            case SIGIOT: case SIGFPE: case SIGSEGV:
                            case SIGIOT: case SIGFPE: case SIGSEGV:
                                if (current->binfmt && current->binfmt->core_dump) {
                                if (current->binfmt && current->binfmt->core_dump) {
                                    if (current->binfmt->core_dump(signr, (struct pt_regs *)regs))
                                    if (current->binfmt->core_dump(signr, (struct pt_regs *)regs))
                                        signr |= 0x80;
                                        signr |= 0x80;
                                }
                                }
                                /* fall through */
                                /* fall through */
                            default:
                            default:
                                current->signal |= _S(signr & 0x7f);
                                current->signal |= _S(signr & 0x7f);
                                do_exit(signr);
                                do_exit(signr);
                        }
                        }
                }
                }
                /*
                /*
                 * OK, we're invoking a handler
                 * OK, we're invoking a handler
                 */
                 */
                if (regs->ptregs.orig_d0 >= 0) {
                if (regs->ptregs.orig_d0 >= 0) {
                  if (regs->ptregs.d0 == -ERESTARTNOHAND ||
                  if (regs->ptregs.d0 == -ERESTARTNOHAND ||
                      (regs->ptregs.d0 == -ERESTARTSYS &&
                      (regs->ptregs.d0 == -ERESTARTSYS &&
                       !(sa->sa_flags & SA_RESTART)))
                       !(sa->sa_flags & SA_RESTART)))
                    regs->ptregs.d0 = -EINTR;
                    regs->ptregs.d0 = -EINTR;
                }
                }
                handler_signal |= 1 << (signr-1);
                handler_signal |= 1 << (signr-1);
                mask &= ~sa->sa_mask;
                mask &= ~sa->sa_mask;
        }
        }
        if (regs->ptregs.orig_d0 >= 0 &&
        if (regs->ptregs.orig_d0 >= 0 &&
            (regs->ptregs.d0 == -ERESTARTNOHAND ||
            (regs->ptregs.d0 == -ERESTARTNOHAND ||
             regs->ptregs.d0 == -ERESTARTSYS ||
             regs->ptregs.d0 == -ERESTARTSYS ||
             regs->ptregs.d0 == -ERESTARTNOINTR)) {
             regs->ptregs.d0 == -ERESTARTNOINTR)) {
                regs->ptregs.d0 = regs->ptregs.orig_d0;
                regs->ptregs.d0 = regs->ptregs.orig_d0;
                regs->ptregs.pc -= 2;
                regs->ptregs.pc -= 2;
        }
        }
        if (!handler_signal)    /* no handler will be called - return 0 */
        if (!handler_signal)    /* no handler will be called - return 0 */
          {
          {
            /* If we are about to discard some frame stuff we must
            /* If we are about to discard some frame stuff we must
               copy over the remaining frame. */
               copy over the remaining frame. */
            if (regs->ptregs.stkadj)
            if (regs->ptregs.stkadj)
              {
              {
                struct frame *tregs =
                struct frame *tregs =
                  (struct frame *) ((ulong) regs + regs->ptregs.stkadj);
                  (struct frame *) ((ulong) regs + regs->ptregs.stkadj);
 
 
                /* This must be copied with decreasing addresses to
                /* This must be copied with decreasing addresses to
                   handle overlaps.  */
                   handle overlaps.  */
                tregs->ptregs.vector = regs->ptregs.vector;
                tregs->ptregs.vector = regs->ptregs.vector;
                tregs->ptregs.format = regs->ptregs.format;
                tregs->ptregs.format = regs->ptregs.format;
                tregs->ptregs.pc = regs->ptregs.pc;
                tregs->ptregs.pc = regs->ptregs.pc;
                tregs->ptregs.sr = regs->ptregs.sr;
                tregs->ptregs.sr = regs->ptregs.sr;
              }
              }
            return 0;
            return 0;
          }
          }
        pc = regs->ptregs.pc;
        pc = regs->ptregs.pc;
        frame = (unsigned long *)rdusp();
        frame = (unsigned long *)rdusp();
        signr = 1;
        signr = 1;
        sa = current->sig->action;
        sa = current->sig->action;
        for (mask = 1 ; mask ; sa++,signr++,mask += mask) {
        for (mask = 1 ; mask ; sa++,signr++,mask += mask) {
                if (mask > handler_signal)
                if (mask > handler_signal)
                        break;
                        break;
                if (!(mask & handler_signal))
                if (!(mask & handler_signal))
                        continue;
                        continue;
                setup_frame(sa,&frame,pc,regs,signr,oldmask);
                setup_frame(sa,&frame,pc,regs,signr,oldmask);
                pc = (unsigned long) sa->sa_handler;
                pc = (unsigned long) sa->sa_handler;
                if (sa->sa_flags & SA_ONESHOT)
                if (sa->sa_flags & SA_ONESHOT)
                        sa->sa_handler = NULL;
                        sa->sa_handler = NULL;
/* force a supervisor-mode page-in of the signal handler to reduce races */
/* force a supervisor-mode page-in of the signal handler to reduce races */
                __asm__ __volatile__("movesb %0,%/d0": :"m" (*(char *)pc):"d0");
                __asm__ __volatile__("movesb %0,%/d0": :"m" (*(char *)pc):"d0");
                current->blocked |= sa->sa_mask;
                current->blocked |= sa->sa_mask;
                oldmask |= sa->sa_mask;
                oldmask |= sa->sa_mask;
        }
        }
        wrusp((unsigned long)frame);
        wrusp((unsigned long)frame);
        regs->ptregs.pc = pc;
        regs->ptregs.pc = pc;
 
 
        /*
        /*
         * if setup_frame saved some extra frame junk, we need to
         * if setup_frame saved some extra frame junk, we need to
         * skip over that stuff when doing the RTE.  This means we have
         * skip over that stuff when doing the RTE.  This means we have
         * to move the machine portion of the stack frame to where the
         * to move the machine portion of the stack frame to where the
         * "RTE" instruction expects it. The signal that we need to
         * "RTE" instruction expects it. The signal that we need to
         * do this is that regs->stkadj is nonzero.
         * do this is that regs->stkadj is nonzero.
         */
         */
        if (regs->ptregs.stkadj) {
        if (regs->ptregs.stkadj) {
                struct frame *tregs =
                struct frame *tregs =
                        (struct frame *)((ulong)regs + regs->ptregs.stkadj);
                        (struct frame *)((ulong)regs + regs->ptregs.stkadj);
#if DEBUG
#if DEBUG
          printk("Performing stackadjust=%04x\n", (unsigned)
          printk("Performing stackadjust=%04x\n", (unsigned)
                 regs->ptregs.stkadj);
                 regs->ptregs.stkadj);
#endif
#endif
                /* This must be copied with decreasing addresses to
                /* This must be copied with decreasing addresses to
                   handle overlaps.  */
                   handle overlaps.  */
                tregs->ptregs.vector = regs->ptregs.vector;
                tregs->ptregs.vector = regs->ptregs.vector;
                tregs->ptregs.format = regs->ptregs.format;
                tregs->ptregs.format = regs->ptregs.format;
                tregs->ptregs.pc = regs->ptregs.pc;
                tregs->ptregs.pc = regs->ptregs.pc;
                tregs->ptregs.sr = regs->ptregs.sr;
                tregs->ptregs.sr = regs->ptregs.sr;
        }
        }
 
 
        return 1;
        return 1;
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.