root/arch/mips/kernel/signal.c

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

DEFINITIONS

This source file includes following definitions.
  1. sys_sigsuspend
  2. sys_sigreturn
  3. setup_frame
  4. do_signal

   1 /*
   2  *  linux/arch/mips/kernel/signal.c
   3  *
   4  *  Copyright (C) 1991, 1992  Linus Torvalds
   5  */
   6 #include <linux/sched.h>
   7 #include <linux/mm.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 
  15 #include <asm/bitops.h>
  16 #include <asm/segment.h>
  17 #include <asm/cachectl.h>
  18 
  19 #define _S(nr) (1<<((nr)-1))
  20 
  21 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
  22 
  23 asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
  24 asmlinkage int do_signal(unsigned long oldmask, struct pt_regs *regs);
  25 
  26 /*
  27  * atomically swap in the new signal mask, and wait for a signal.
  28  */
  29 asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, unsigned long set)
     /* [previous][next][first][last][top][bottom][index][help] */
  30 {
  31         unsigned long mask;
  32         struct pt_regs * regs = (struct pt_regs *) &restart;
  33 
  34         mask = current->blocked;
  35         current->blocked = set & _BLOCKABLE;
  36         regs->reg2 = -EINTR;
  37         while (1) {
  38                 current->state = TASK_INTERRUPTIBLE;
  39                 schedule();
  40                 if (do_signal(mask,regs))
  41                         return -EINTR;
  42         }
  43 }
  44 
  45 /*
  46  * This sets regs->reg29 even though we don't actually use sigstacks yet..
  47  */
  48 asmlinkage int sys_sigreturn(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
  49 {
  50         struct sigcontext_struct *context;
  51 
  52         /*
  53          * We don't support fixing ADEL/ADES exceptions for signal stack frames.
  54          * No big loss - who doesn't care about the alignment of this stack
  55          * really deserves to loose.
  56          */
  57         context = (struct sigcontext_struct *) regs->reg29;
  58         if (verify_area(VERIFY_READ, context, sizeof(struct sigcontext_struct)) ||
  59             (regs->reg29 & 3))
  60                 goto badframe;
  61 
  62         current->blocked = context->sc_oldmask & _BLOCKABLE;
  63         regs->reg1  = context->sc_at;
  64         regs->reg2  = context->sc_v0;
  65         regs->reg3  = context->sc_v1;
  66         regs->reg4  = context->sc_a0;
  67         regs->reg5  = context->sc_a1;
  68         regs->reg6  = context->sc_a2;
  69         regs->reg7  = context->sc_a3;
  70         regs->reg8  = context->sc_t0;
  71         regs->reg9  = context->sc_t1;
  72         regs->reg10 = context->sc_t2;
  73         regs->reg11 = context->sc_t3;
  74         regs->reg12 = context->sc_t4;
  75         regs->reg13 = context->sc_t5;
  76         regs->reg14 = context->sc_t6;
  77         regs->reg15 = context->sc_t7;
  78         regs->reg16 = context->sc_s0;
  79         regs->reg17 = context->sc_s1;
  80         regs->reg18 = context->sc_s2;
  81         regs->reg19 = context->sc_s3;
  82         regs->reg20 = context->sc_s4;
  83         regs->reg21 = context->sc_s5;
  84         regs->reg22 = context->sc_s6;
  85         regs->reg23 = context->sc_s7;
  86         regs->reg24 = context->sc_t8;
  87         regs->reg25 = context->sc_t9;
  88         /*
  89          * Skip k0/k1
  90          */
  91         regs->reg28 = context->sc_gp;
  92         regs->reg29 = context->sc_sp;
  93         regs->reg30 = context->sc_fp;
  94         regs->reg31 = context->sc_ra;
  95         regs->cp0_epc = context->sc_epc;
  96         regs->cp0_cause = context->sc_cause;
  97 
  98         /*
  99          * disable syscall checks
 100          */
 101         regs->orig_reg2 = -1;
 102         return context->sc_v0;
 103 
 104 badframe:
 105         do_exit(SIGSEGV);
 106 }
 107 
 108 /*
 109  * Set up a signal frame...
 110  *
 111  * This routine is somewhat complicated by the fact that if the kernel may be
 112  * entered by an exception other than a system call; e.g. a bus error or other
 113  * "bad" exception.  If this is the case, then *all* the context on the kernel
 114  * stack frame must be saved.
 115  *
 116  * For a large number of exceptions, the stack frame format is the same
 117  * as that which will be created when the process traps back to the kernel
 118  * when finished executing the signal handler.  In this case, nothing
 119  * must be done. This information is saved on the user stack and restored
 120  * when the signal handler is returned.
 121  *
 122  * The signal handler will be called with ra pointing to code1 (see below) and
 123  * one parameters in a0 (signum).
 124  *
 125  *     usp ->  [unused]                         ; first free word on stack
 126  *             arg save space                   ; 16 bytes argument save space
 127  *             code1   (addiu sp,#1-offset)     ; syscall number
 128  *             code2   (li v0,__NR_sigreturn)   ; syscall number
 129  *             code3   (syscall)                ; do sigreturn(2)
 130  *     #1|     at, v0, v1, a0, a1, a2, a3       ; All integer registers
 131  *       |     t0, t1, t2, t3, t4, t5, t6, t7   ; except zero, k0 and k1
 132  *       |     s0, s1, s2, s3, s4, s5, s6, s7
 133  *       |     t8, t9, gp, sp, fp, ra;
 134  *       |     epc                              ; old program counter
 135  *       |     cause                            ; CP0 cause register
 136  *       |     oldmask
 137  */
 138 
 139 struct sc {
 140         unsigned long   ass[4];
 141         unsigned int    code[4];
 142         struct sigcontext_struct scc;
 143 };
 144 #define scc_offset ((size_t)&((struct sc *)0)->scc)
 145 
 146 static void setup_frame(struct sigaction * sa, struct sc **fp,
     /* [previous][next][first][last][top][bottom][index][help] */
 147                         unsigned long pc, struct pt_regs *regs,
 148                         int signr, unsigned long oldmask)
 149 {
 150         struct sc *frame;
 151 
 152         frame = *fp;
 153         frame--;
 154 
 155         /*
 156          * We don't support fixing ADEL/ADES exceptions for signal stack frames.
 157          * No big loss - who doesn't care about the alignment of this stack
 158          * really deserves to loose.
 159          */
 160         if (verify_area(VERIFY_WRITE, frame, sizeof (struct sc)) ||
 161             ((unsigned long)frame & 3))
 162                 do_exit(SIGSEGV);
 163 
 164         /*
 165          * Set up the return code ...
 166          *
 167          *         .set    noreorder
 168          *         addiu   sp,24
 169          *         li      v0,__NR_sigreturn
 170          *         syscall
 171          *         .set    reorder
 172          */
 173         frame->code[0] = 0x27bd0000 + scc_offset;
 174         frame->code[1] = 0x24020000 + __NR_sigreturn;
 175         frame->code[2] = 0x0000000c;
 176 
 177         /*
 178          * Flush caches so that the instructions will be correctly executed.
 179          */
 180         sys_cacheflush (frame->code, sizeof (frame->code), ICACHE);
 181 
 182         /*
 183          * Set up the "normal" sigcontext_struct
 184          */
 185         frame->scc.sc_at = regs->reg1;          /* Assembler temporary */
 186         frame->scc.sc_v0 = regs->reg2;          /* Result registers */
 187         frame->scc.sc_v1 = regs->reg3;
 188         frame->scc.sc_a0 = regs->reg4;          /* Argument registers */
 189         frame->scc.sc_a1 = regs->reg5;
 190         frame->scc.sc_a2 = regs->reg6;
 191         frame->scc.sc_a3 = regs->reg7;
 192 
 193         frame->scc.sc_t0 = regs->reg8;          /* Caller saved */
 194         frame->scc.sc_t1 = regs->reg9;
 195         frame->scc.sc_t2 = regs->reg10;
 196         frame->scc.sc_t3 = regs->reg11;
 197         frame->scc.sc_t4 = regs->reg12;
 198         frame->scc.sc_t5 = regs->reg13;
 199         frame->scc.sc_t6 = regs->reg14;
 200         frame->scc.sc_t7 = regs->reg15;
 201 
 202         frame->scc.sc_s0 = regs->reg16;         /* Callee saved */
 203         frame->scc.sc_s1 = regs->reg17;
 204         frame->scc.sc_s2 = regs->reg18;
 205         frame->scc.sc_s3 = regs->reg19;
 206         frame->scc.sc_s4 = regs->reg20;
 207         frame->scc.sc_s5 = regs->reg21;
 208         frame->scc.sc_s6 = regs->reg22;
 209         frame->scc.sc_s7 = regs->reg23;
 210 
 211         frame->scc.sc_t8 = regs->reg24;         /* Caller saved */
 212         frame->scc.sc_t9 = regs->reg25;
 213 
 214         /*
 215          * Don't copy k0/k1
 216          */
 217         frame->scc.sc_gp = regs->reg28;         /* global pointer / s8 */
 218         frame->scc.sc_sp = regs->reg29;         /* old stack pointer */
 219         frame->scc.sc_fp = regs->reg30;         /* old frame pointer */
 220         frame->scc.sc_ra = regs->reg31;         /* old return address */
 221 
 222         frame->scc.sc_epc = regs->cp0_epc;      /* Program counter */
 223         frame->scc.sc_cause = regs->cp0_cause;  /* c0_epc register */
 224 
 225         frame->scc.sc_oldmask = oldmask;
 226         *fp = frame;
 227 
 228         regs->reg4 = signr;             /* argument for handler */
 229 }
 230 
 231 /*
 232  * Note that 'init' is a special process: it doesn't get signals it doesn't
 233  * want to handle. Thus you cannot kill init even with a SIGKILL even by
 234  * mistake.
 235  *
 236  * Note that we go through the signals twice: once to check the signals that
 237  * the kernel can handle, and then we build all the user-level signal handling
 238  * stack-frames in one go after that.
 239  */
 240 asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 241 {
 242         unsigned long mask = ~current->blocked;
 243         unsigned long handler_signal = 0;
 244         struct sc *frame = NULL;
 245         unsigned long pc = 0;
 246         unsigned long signr;
 247         struct sigaction * sa;
 248 
 249         while ((signr = current->signal & mask)) {
 250                 signr = ffz(~signr);
 251                 clear_bit(signr, &current->signal);
 252                 sa = current->sig->action + signr;
 253                 signr++;
 254                 if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
 255                         current->exit_code = signr;
 256                         current->state = TASK_STOPPED;
 257                         notify_parent(current);
 258                         schedule();
 259                         if (!(signr = current->exit_code))
 260                                 continue;
 261                         current->exit_code = 0;
 262                         if (signr == SIGSTOP)
 263                                 continue;
 264                         if (_S(signr) & current->blocked) {
 265                                 current->signal |= _S(signr);
 266                                 continue;
 267                         }
 268                         sa = current->sig->action + signr - 1;
 269                 }
 270                 if (sa->sa_handler == SIG_IGN) {
 271                         if (signr != SIGCHLD)
 272                                 continue;
 273                         /* check for SIGCHLD: it's special */
 274                         while (sys_waitpid(-1,NULL,WNOHANG) > 0)
 275                                 /* nothing */;
 276                         continue;
 277                 }
 278                 if (sa->sa_handler == SIG_DFL) {
 279                         if (current->pid == 1)
 280                                 continue;
 281                         switch (signr) {
 282                         case SIGCONT: case SIGCHLD: case SIGWINCH:
 283                                 continue;
 284 
 285                         case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU:
 286                                 if (current->flags & PF_PTRACED)
 287                                         continue;
 288                                 current->state = TASK_STOPPED;
 289                                 current->exit_code = signr;
 290                                 if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & 
 291                                                 SA_NOCLDSTOP))
 292                                         notify_parent(current);
 293                                 schedule();
 294                                 continue;
 295 
 296                         case SIGQUIT: case SIGILL: case SIGTRAP:
 297                         case SIGIOT: case SIGFPE: case SIGSEGV: case SIGBUS:
 298                                 if (current->binfmt && current->binfmt->core_dump) {
 299                                         if (current->binfmt->core_dump(signr, regs))
 300                                                 signr |= 0x80;
 301                                 }
 302                                 /* fall through */
 303                         default:
 304                                 current->signal |= _S(signr & 0x7f);
 305                                 do_exit(signr);
 306                         }
 307                 }
 308                 /*
 309                  * OK, we're invoking a handler
 310                  */
 311                 if (regs->orig_reg2 >= 0) {
 312                         if (regs->reg2 == -ERESTARTNOHAND ||
 313                            (regs->reg2 == -ERESTARTSYS &&
 314                             !(sa->sa_flags & SA_RESTART)))
 315                                 regs->reg2 = -EINTR;
 316                 }
 317                 handler_signal |= 1 << (signr-1);
 318                 mask &= ~sa->sa_mask;
 319         }
 320         /*
 321          * Who's code doesn't conform to the restartable syscall convention
 322          * dies here!!!  The li instruction, a single machine instruction,
 323          * must directly be followed by the syscall instruction.
 324          */
 325         if (regs->orig_reg2 >= 0 &&
 326             (regs->reg2 == -ERESTARTNOHAND ||
 327              regs->reg2 == -ERESTARTSYS ||
 328              regs->reg2 == -ERESTARTNOINTR))
 329         {
 330                 regs->reg2 = regs->orig_reg2;
 331                 regs->cp0_epc -= 8;
 332         }
 333         if (!handler_signal)            /* no handler will be called - return 0 */
 334                 return 0;
 335         pc = regs->cp0_epc;
 336         frame = (struct sc *) regs->reg29;
 337         signr = 1;
 338         sa = current->sig->action;
 339         for (mask = 1 ; mask ; sa++,signr++,mask += mask) {
 340                 if (mask > handler_signal)
 341                         break;
 342                 if (!(mask & handler_signal))
 343                         continue;
 344                 setup_frame(sa, &frame, pc, regs, signr, oldmask);
 345                 pc = (unsigned long) sa->sa_handler;
 346                 if (sa->sa_flags & SA_ONESHOT)
 347                         sa->sa_handler = NULL;
 348                 current->blocked |= sa->sa_mask;
 349                 oldmask |= sa->sa_mask;
 350         }
 351         regs->reg29 = (unsigned long) frame;            /* Stack pointer */
 352         regs->reg31 = (unsigned long) frame->code;      /* Return address */
 353         regs->cp0_epc = pc;             /* "return" to the first handler */
 354 
 355         return 1;
 356 }

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