root/arch/sparc/kernel/signal.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _sigpause_common
  2. do_sigpause
  3. do_sigsuspend
  4. do_sigreturn
  5. setup_frame
  6. do_signal
  7. sys_sigstack

   1 /*  $Id: signal.c,v 1.28 1995/12/29 21:47:18 davem Exp $
   2  *  linux/arch/sparc/kernel/signal.c
   3  *
   4  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
   5  */
   6 
   7 #include <linux/sched.h>
   8 #include <linux/kernel.h>
   9 #include <linux/signal.h>
  10 #include <linux/errno.h>
  11 #include <linux/wait.h>
  12 #include <linux/ptrace.h>
  13 #include <linux/unistd.h>
  14 #include <linux/mm.h>
  15 
  16 #include <asm/segment.h>
  17 #include <asm/bitops.h>
  18 #include <asm/ptrace.h>
  19 
  20 #define _S(nr) (1<<((nr)-1))
  21 
  22 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
  23 
  24 asmlinkage int sys_waitpid(pid_t pid, unsigned long *stat_addr, int options);
  25 asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs);
  26 
  27 /*
  28  * atomically swap in the new signal mask, and wait for a signal.
  29  * This is really tricky on the Sparc, watch out...
  30  */
  31 asmlinkage inline void _sigpause_common(unsigned int set, struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
  32 {
  33         unsigned long mask;
  34 
  35         mask = current->blocked;
  36         current->blocked = set & _BLOCKABLE;
  37 
  38         /* Advance over the syscall instruction for when
  39          * we return.  We want setup_frame to save the proper
  40          * state, including the error return number & condition
  41          * codes.
  42          */
  43         regs->pc = regs->npc;
  44         regs->npc += 4;
  45         regs->psr |= PSR_C;
  46         regs->u_regs[UREG_I0] = EINTR;
  47 
  48         while (1) {
  49                 current->state = TASK_INTERRUPTIBLE;
  50                 schedule();
  51                 if (do_signal(mask, regs))
  52                         return;
  53         }
  54 }
  55 
  56 asmlinkage void do_sigpause(unsigned int set, struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
  57 {
  58         _sigpause_common(set, regs);
  59 }
  60 
  61 asmlinkage void do_sigsuspend(unsigned int *sigmaskp, struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
  62 {
  63         unsigned int set;
  64 
  65         /* Manual does not state what is supposed to happen if
  66          * the sigmask ptr is bogus.  It does state that EINTR
  67          * is the only valid return value and it indicates
  68          * successful signal delivery.  Must investigate.
  69          */
  70         if(verify_area(VERIFY_READ, sigmaskp, sizeof(unsigned int))) {
  71                 regs->pc = regs->npc;
  72                 regs->npc += 4;
  73                 regs->u_regs[UREG_I0] = EFAULT;
  74                 regs->psr |= PSR_C;
  75                 return;
  76         }
  77         set = *sigmaskp;
  78         _sigpause_common(set, regs);
  79 }
  80 
  81 asmlinkage void do_sigreturn(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
  82 {
  83         struct sigcontext_struct *scptr =
  84                 (struct sigcontext_struct *) regs->u_regs[UREG_I0];
  85 
  86         synchronize_user_stack();
  87 
  88         /* Check sanity of the user arg. */
  89         if(verify_area(VERIFY_READ, scptr, sizeof(struct sigcontext_struct)) ||
  90            ((((unsigned long) scptr)) & 0x3)) {
  91                 printk("%s [%d]: do_sigreturn, scptr is invalid at pc<%08lx> scptr<%p>\n",
  92                        current->comm, current->pid, regs->pc, scptr);
  93                 do_exit(SIGSEGV);
  94         }
  95 
  96         if((scptr->sigc_pc | scptr->sigc_npc) & 3)
  97                 return; /* Nice try. */
  98 
  99         current->blocked = scptr->sigc_mask & _BLOCKABLE;
 100         current->tss.sstk_info.cur_status = (scptr->sigc_onstack & 1);
 101         regs->pc = scptr->sigc_pc;
 102         regs->npc = scptr->sigc_npc;
 103         regs->u_regs[UREG_FP] = scptr->sigc_sp;
 104         regs->u_regs[UREG_I0] = scptr->sigc_o0;
 105         regs->u_regs[UREG_G1] = scptr->sigc_g1;
 106 
 107         /* User can only change condition codes in %psr. */
 108         regs->psr &= (~PSR_ICC);
 109         regs->psr |= (scptr->sigc_psr & PSR_ICC);
 110 }
 111 
 112 /*
 113  * Set up a signal frame... Make the stack look the way SunOS
 114  * expects it to look which is basically:
 115  *
 116  * ---------------------------------- <-- %sp at signal time
 117  * Struct sigcontext
 118  * Signal address
 119  * Ptr to sigcontext area above
 120  * Signal code
 121  * The signal number itself
 122  * One register window
 123  * ---------------------------------- <-- New %sp
 124  */
 125 struct signal_sframe {
 126         struct reg_window sig_window;
 127         int sig_num;
 128         int sig_code;
 129         struct sigcontext_struct *sig_scptr;
 130         int sig_address;
 131         struct sigcontext_struct sig_context;
 132 };
 133 /* To align the structure properly. */
 134 #define SF_ALIGNEDSZ  (((sizeof(struct signal_sframe) + 7) & (~7)))
 135 
 136 static inline void
 137 setup_frame(struct sigaction *sa, struct sigcontext_struct **fp,
     /* [previous][next][first][last][top][bottom][index][help] */
 138             unsigned long pc, unsigned long npc, struct pt_regs *regs,
 139             int signr, unsigned long oldmask)
 140 {
 141         struct signal_sframe *sframep;
 142         struct sigcontext_struct *sc;
 143         int window = 0;
 144         int old_status = current->tss.sstk_info.cur_status;
 145 
 146         synchronize_user_stack();
 147         sframep = (struct signal_sframe *) *fp;
 148         sframep = (struct signal_sframe *) (((unsigned long) sframep)-SF_ALIGNEDSZ);
 149         sc = &sframep->sig_context;
 150         if(verify_area(VERIFY_WRITE, sframep, sizeof(*sframep)) ||
 151            (((unsigned long) sframep) & 7) ||
 152            (((unsigned long) sframep) >= KERNBASE) ||
 153            ((sparc_cpu_model == sun4 || sparc_cpu_model == sun4c) &&
 154             ((unsigned long) sframep < 0xe0000000 && (unsigned long) sframep >= 0x20000000))) {
 155                 printk("%s [%d]: User has trashed signal stack\n",
 156                        current->comm, current->pid);
 157                 printk("Sigstack ptr %p handler at pc<%08lx> for sig<%d>\n",
 158                        sframep, pc, signr);
 159                 /* Don't change signal code and address, so that
 160                  * post mortem debuggers can have a look.
 161                  */
 162                 current->sig->action[SIGILL-1].sa_handler = SIG_DFL;
 163                 current->blocked &= ~(1<<(SIGILL-1));
 164                 send_sig(SIGILL,current,1);
 165                 return;
 166         }
 167         *fp = (struct sigcontext_struct *) sframep;
 168 
 169         sc->sigc_onstack = old_status;
 170         sc->sigc_mask = oldmask;
 171         sc->sigc_sp = regs->u_regs[UREG_FP];
 172         sc->sigc_pc = pc;
 173         sc->sigc_npc = npc;
 174         sc->sigc_psr = regs->psr;
 175         sc->sigc_g1 = regs->u_regs[UREG_G1];
 176         sc->sigc_o0 = regs->u_regs[UREG_I0];
 177         sc->sigc_oswins = current->tss.w_saved;
 178         if(current->tss.w_saved)
 179                 for(window = 0; window < current->tss.w_saved; window++) {
 180                         sc->sigc_spbuf[window] =
 181                                 (char *)current->tss.rwbuf_stkptrs[window];
 182                         memcpy(&sc->sigc_wbuf[window],
 183                                &current->tss.reg_window[window],
 184                                sizeof(struct reg_window));
 185                 }
 186         else
 187                 memcpy(sframep, (char *)regs->u_regs[UREG_FP],
 188                        sizeof(struct reg_window));
 189 
 190         current->tss.w_saved = 0; /* So process is allowed to execute. */
 191         sframep->sig_num = signr;
 192         if(signr == SIGSEGV ||
 193            signr == SIGILL ||
 194            signr == SIGFPE ||
 195            signr == SIGBUS ||
 196            signr == SIGEMT) {
 197                 sframep->sig_code = current->tss.sig_desc;
 198                 sframep->sig_address = current->tss.sig_address;
 199         } else {
 200                 sframep->sig_code = 0;
 201                 sframep->sig_address = 0;
 202         }
 203         sframep->sig_scptr = sc;
 204         regs->u_regs[UREG_FP] = (unsigned long) *fp;
 205 }
 206 
 207 /*
 208  * Note that 'init' is a special process: it doesn't get signals it doesn't
 209  * want to handle. Thus you cannot kill init even with a SIGKILL even by
 210  * mistake.
 211  *
 212  * Note that we go through the signals twice: once to check the signals that
 213  * the kernel can handle, and then we build all the user-level signal handling
 214  * stack-frames in one go after that.
 215  */
 216 
 217 asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 218 {
 219         unsigned long mask = ~current->blocked;
 220         unsigned long handler_signal = 0;
 221         struct sigcontext_struct *frame = NULL;
 222         unsigned long pc = 0;
 223         unsigned long npc = 0;
 224         unsigned long signr;
 225         struct sigaction *sa;
 226 
 227         while ((signr = current->signal & mask) != 0) {
 228                 signr = ffz(~signr);
 229                 clear_bit(signr, &current->signal);
 230                 sa = current->sig->action + signr;
 231                 signr++;
 232                 if(sa->sa_handler == SIG_IGN) {
 233                         if(signr != SIGCHLD)
 234                                 continue;
 235                         while(sys_waitpid(-1,NULL,WNOHANG) > 0);
 236                         continue;
 237                 }
 238                 if(sa->sa_handler == SIG_DFL) {
 239                         if(current->pid == 1)
 240                                 continue;
 241                         switch(signr) {
 242                         case SIGCONT: case SIGCHLD: case SIGWINCH:
 243                                 continue;
 244 
 245                         case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU:
 246                                 current->state = TASK_STOPPED;
 247                                 current->exit_code = signr;
 248                                 if(!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags &
 249                                      SA_NOCLDSTOP))
 250                                         notify_parent(current);
 251                                 schedule();
 252                                 continue;
 253 
 254                         case SIGQUIT: case SIGILL: case SIGTRAP:
 255                         case SIGABRT: case SIGFPE: case SIGSEGV:
 256                                 if(current->binfmt && current->binfmt->core_dump) {
 257                                         if(current->binfmt->core_dump(signr, regs))
 258                                                 signr |= 0x80;
 259                                 }
 260                                 /* fall through */
 261                         default:
 262                                 current->signal |= _S(signr & 0x7f);
 263                                 current->flags |= PF_SIGNALED;
 264                                 do_exit(signr);
 265                         }
 266                 }
 267                 /* OK, we're invoking a handler. */
 268                 if(regs->psr & PSR_C) {
 269                         if(regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
 270                            (regs->u_regs[UREG_I0] == ERESTARTSYS && !(sa->sa_flags & SA_RESTART)))
 271                                 regs->u_regs[UREG_I0] = EINTR;
 272                 }
 273                 handler_signal |= 1 << (signr - 1);
 274                 mask &= ~sa->sa_mask;
 275         }
 276         if((regs->psr & PSR_C) &&
 277            (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
 278             regs->u_regs[UREG_I0] == ERESTARTSYS ||
 279             regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
 280                 /* replay the system call when we are done */
 281                 regs->u_regs[UREG_I0] = regs->u_regs[UREG_G0];
 282                 regs->pc -= 4;
 283                 regs->npc -= 4;
 284         }
 285         if(!handler_signal)
 286                 return 0;
 287         pc = regs->pc;
 288         npc = regs->npc;
 289         frame = (struct sigcontext_struct *) regs->u_regs[UREG_FP];
 290         signr = 1;
 291         sa = current->sig->action;
 292         for(mask = 1; mask; sa++, signr++, mask += mask) {
 293                 if(mask > handler_signal)
 294                         break;
 295                 if(!(mask & handler_signal))
 296                         continue;
 297                 setup_frame(sa, &frame, pc, npc, regs, signr, oldmask);
 298                 pc = (unsigned long) sa->sa_handler;
 299                 npc = pc + 4;
 300                 if(sa->sa_flags & SA_ONESHOT)
 301                         sa->sa_handler = NULL;
 302                 current->blocked |= sa->sa_mask;
 303                 oldmask |= sa->sa_mask;
 304         }
 305         regs->pc = pc;
 306         regs->npc = npc;
 307         return 1;
 308 }
 309 
 310 asmlinkage int
 311 sys_sigstack(struct sigstack *ssptr, struct sigstack *ossptr)
     /* [previous][next][first][last][top][bottom][index][help] */
 312 {
 313         /* First see if old state is wanted. */
 314         if(ossptr) {
 315                 if(verify_area(VERIFY_WRITE, ossptr, sizeof(struct sigstack)))
 316                         return -EFAULT;
 317                 memcpy(ossptr, &current->tss.sstk_info, sizeof(struct sigstack));
 318         }
 319 
 320         /* Now see if we want to update the new state. */
 321         if(ssptr) {
 322                 if(verify_area(VERIFY_READ, ssptr, sizeof(struct sigstack)))
 323                         return -EFAULT;
 324                 memcpy(&current->tss.sstk_info, ssptr, sizeof(struct sigstack));
 325         }
 326         return 0;
 327 }

/* [previous][next][first][last][top][bottom][index][help] */