Pull trivial into test branch
[linux-2.6] / arch / v850 / kernel / signal.c
1 /*
2  * arch/v850/kernel/signal.c -- Signal handling
3  *
4  *  Copyright (C) 2001,02,03  NEC Electronics Corporation
5  *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
6  *  Copyright (C) 1999,2000,2002  Niibe Yutaka & Kaz Kojima
7  *  Copyright (C) 1991,1992  Linus Torvalds
8  *
9  * This file is subject to the terms and conditions of the GNU General
10  * Public License.  See the file COPYING in the main directory of this
11  * archive for more details.
12  *
13  * 1997-11-28  Modified for POSIX.1b signals by Richard Henderson
14  *
15  * This file was derived from the sh version, arch/sh/kernel/signal.c
16  */
17
18 #include <linux/mm.h>
19 #include <linux/smp.h>
20 #include <linux/smp_lock.h>
21 #include <linux/kernel.h>
22 #include <linux/signal.h>
23 #include <linux/errno.h>
24 #include <linux/wait.h>
25 #include <linux/ptrace.h>
26 #include <linux/unistd.h>
27 #include <linux/stddef.h>
28 #include <linux/personality.h>
29 #include <linux/tty.h>
30
31 #include <asm/ucontext.h>
32 #include <asm/uaccess.h>
33 #include <asm/pgtable.h>
34 #include <asm/pgalloc.h>
35 #include <asm/thread_info.h>
36 #include <asm/cacheflush.h>
37
38 #define DEBUG_SIG 0
39
40 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
41
42 asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
43
44 /*
45  * Atomically swap in the new signal mask, and wait for a signal.
46  */
47 asmlinkage int
48 sys_sigsuspend(old_sigset_t mask, struct pt_regs *regs)
49 {
50         sigset_t saveset;
51
52         mask &= _BLOCKABLE;
53         spin_lock_irq(&current->sighand->siglock);
54         saveset = current->blocked;
55         siginitset(&current->blocked, mask);
56         recalc_sigpending();
57         spin_unlock_irq(&current->sighand->siglock);
58
59         regs->gpr[GPR_RVAL] = -EINTR;
60         while (1) {
61                 current->state = TASK_INTERRUPTIBLE;
62                 schedule();
63                 if (do_signal(regs, &saveset))
64                         return -EINTR;
65         }
66 }
67
68 asmlinkage int
69 sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize,
70                   struct pt_regs *regs)
71 {
72         sigset_t saveset, newset;
73
74         /* XXX: Don't preclude handling different sized sigset_t's.  */
75         if (sigsetsize != sizeof(sigset_t))
76                 return -EINVAL;
77
78         if (copy_from_user(&newset, unewset, sizeof(newset)))
79                 return -EFAULT;
80         sigdelsetmask(&newset, ~_BLOCKABLE);
81         spin_lock_irq(&current->sighand->siglock);
82         saveset = current->blocked;
83         current->blocked = newset;
84         recalc_sigpending();
85         spin_unlock_irq(&current->sighand->siglock);
86
87         regs->gpr[GPR_RVAL] = -EINTR;
88         while (1) {
89                 current->state = TASK_INTERRUPTIBLE;
90                 schedule();
91                 if (do_signal(regs, &saveset))
92                         return -EINTR;
93         }
94 }
95
96 asmlinkage int 
97 sys_sigaction(int sig, const struct old_sigaction *act,
98               struct old_sigaction *oact)
99 {
100         struct k_sigaction new_ka, old_ka;
101         int ret;
102
103         if (act) {
104                 old_sigset_t mask;
105                 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
106                     __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
107                     __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
108                         return -EFAULT;
109                 __get_user(new_ka.sa.sa_flags, &act->sa_flags);
110                 __get_user(mask, &act->sa_mask);
111                 siginitset(&new_ka.sa.sa_mask, mask);
112         }
113
114         ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
115
116         if (!ret && oact) {
117                 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
118                     __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
119                     __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
120                         return -EFAULT;
121                 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
122                 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
123         }
124
125         return ret;
126 }
127
128 asmlinkage int
129 sys_sigaltstack(const stack_t *uss, stack_t *uoss,
130                 struct pt_regs *regs)
131 {
132         return do_sigaltstack(uss, uoss, regs->gpr[GPR_SP]);
133 }
134
135
136 /*
137  * Do a signal return; undo the signal stack.
138  */
139
140 struct sigframe
141 {
142         struct sigcontext sc;
143         unsigned long extramask[_NSIG_WORDS-1];
144         unsigned long tramp[2]; /* signal trampoline */
145 };
146
147 struct rt_sigframe
148 {
149         struct siginfo info;
150         struct ucontext uc;
151         unsigned long tramp[2]; /* signal trampoline */
152 };
153
154 static int
155 restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *rval_p)
156 {
157         unsigned int err = 0;
158
159 #define COPY(x)         err |= __get_user(regs->x, &sc->regs.x)
160         COPY(gpr[0]);   COPY(gpr[1]);   COPY(gpr[2]);   COPY(gpr[3]);
161         COPY(gpr[4]);   COPY(gpr[5]);   COPY(gpr[6]);   COPY(gpr[7]);
162         COPY(gpr[8]);   COPY(gpr[9]);   COPY(gpr[10]);  COPY(gpr[11]);
163         COPY(gpr[12]);  COPY(gpr[13]);  COPY(gpr[14]);  COPY(gpr[15]);
164         COPY(gpr[16]);  COPY(gpr[17]);  COPY(gpr[18]);  COPY(gpr[19]);
165         COPY(gpr[20]);  COPY(gpr[21]);  COPY(gpr[22]);  COPY(gpr[23]);
166         COPY(gpr[24]);  COPY(gpr[25]);  COPY(gpr[26]);  COPY(gpr[27]);
167         COPY(gpr[28]);  COPY(gpr[29]);  COPY(gpr[30]);  COPY(gpr[31]);
168         COPY(pc);       COPY(psw);
169         COPY(ctpc);     COPY(ctpsw);    COPY(ctbp);
170 #undef COPY
171
172         return err;
173 }
174
175 asmlinkage int sys_sigreturn(struct pt_regs *regs)
176 {
177         struct sigframe *frame = (struct sigframe *)regs->gpr[GPR_SP];
178         sigset_t set;
179         int rval;
180
181         if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
182                 goto badframe;
183
184         if (__get_user(set.sig[0], &frame->sc.oldmask)
185             || (_NSIG_WORDS > 1
186                 && __copy_from_user(&set.sig[1], &frame->extramask,
187                                     sizeof(frame->extramask))))
188                 goto badframe;
189
190         sigdelsetmask(&set, ~_BLOCKABLE);
191         spin_lock_irq(&current->sighand->siglock);
192         current->blocked = set;
193         recalc_sigpending();
194         spin_unlock_irq(&current->sighand->siglock);
195
196         if (restore_sigcontext(regs, &frame->sc, &rval))
197                 goto badframe;
198         return rval;
199
200 badframe:
201         force_sig(SIGSEGV, current);
202         return 0;
203 }
204
205 asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
206 {
207         struct rt_sigframe *frame = (struct rt_sigframe *)regs->gpr[GPR_SP];
208         sigset_t set;
209         stack_t st;
210         int rval;
211
212         if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
213                 goto badframe;
214
215         if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
216                 goto badframe;
217
218         sigdelsetmask(&set, ~_BLOCKABLE);
219         spin_lock_irq(&current->sighand->siglock);
220         current->blocked = set;
221         recalc_sigpending();
222         spin_unlock_irq(&current->sighand->siglock);
223
224         if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval))
225                 goto badframe;
226
227         if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
228                 goto badframe;
229         /* It is more difficult to avoid calling this function than to
230            call it and ignore errors.  */
231         do_sigaltstack(&st, NULL, regs->gpr[GPR_SP]);
232
233         return rval;
234
235 badframe:
236         force_sig(SIGSEGV, current);
237         return 0;
238 }       
239
240 /*
241  * Set up a signal frame.
242  */
243
244 static int
245 setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
246                  unsigned long mask)
247 {
248         int err = 0;
249
250 #define COPY(x)         err |= __put_user(regs->x, &sc->regs.x)
251         COPY(gpr[0]);   COPY(gpr[1]);   COPY(gpr[2]);   COPY(gpr[3]);
252         COPY(gpr[4]);   COPY(gpr[5]);   COPY(gpr[6]);   COPY(gpr[7]);
253         COPY(gpr[8]);   COPY(gpr[9]);   COPY(gpr[10]);  COPY(gpr[11]);
254         COPY(gpr[12]);  COPY(gpr[13]);  COPY(gpr[14]);  COPY(gpr[15]);
255         COPY(gpr[16]);  COPY(gpr[17]);  COPY(gpr[18]);  COPY(gpr[19]);
256         COPY(gpr[20]);  COPY(gpr[21]);  COPY(gpr[22]);  COPY(gpr[23]);
257         COPY(gpr[24]);  COPY(gpr[25]);  COPY(gpr[26]);  COPY(gpr[27]);
258         COPY(gpr[28]);  COPY(gpr[29]);  COPY(gpr[30]);  COPY(gpr[31]);
259         COPY(pc);       COPY(psw);
260         COPY(ctpc);     COPY(ctpsw);    COPY(ctbp);
261 #undef COPY
262
263         err |= __put_user(mask, &sc->oldmask);
264
265         return err;
266 }
267
268 /*
269  * Determine which stack to use..
270  */
271 static inline void *
272 get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
273 {
274         /* Default to using normal stack */
275         unsigned long sp = regs->gpr[GPR_SP];
276
277         if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
278                 sp = current->sas_ss_sp + current->sas_ss_size;
279
280         return (void *)((sp - frame_size) & -8UL);
281 }
282
283 static void setup_frame(int sig, struct k_sigaction *ka,
284                         sigset_t *set, struct pt_regs *regs)
285 {
286         struct sigframe *frame;
287         int err = 0;
288         int signal;
289
290         frame = get_sigframe(ka, regs, sizeof(*frame));
291
292         if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
293                 goto give_sigsegv;
294
295         signal = current_thread_info()->exec_domain
296                 && current_thread_info()->exec_domain->signal_invmap
297                 && sig < 32
298                 ? current_thread_info()->exec_domain->signal_invmap[sig]
299                 : sig;
300
301         err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
302
303         if (_NSIG_WORDS > 1) {
304                 err |= __copy_to_user(frame->extramask, &set->sig[1],
305                                       sizeof(frame->extramask));
306         }
307
308         /* Set up to return from userspace.  If provided, use a stub
309            already in userspace.  */
310         if (ka->sa.sa_flags & SA_RESTORER) {
311                 regs->gpr[GPR_LP] = (unsigned long) ka->sa.sa_restorer;
312         } else {
313                 /* Note, these encodings are _little endian_!  */
314
315                 /* addi  __NR_sigreturn, r0, r12  */
316                 err |= __put_user(0x6600 | (__NR_sigreturn << 16),
317                                   frame->tramp + 0);
318                 /* trap 0 */
319                 err |= __put_user(0x010007e0,
320                                   frame->tramp + 1);
321
322                 regs->gpr[GPR_LP] = (unsigned long)frame->tramp;
323
324                 flush_cache_sigtramp (regs->gpr[GPR_LP]);
325         }
326
327         if (err)
328                 goto give_sigsegv;
329
330         /* Set up registers for signal handler.  */
331         regs->pc = (v850_reg_t) ka->sa.sa_handler;
332         regs->gpr[GPR_SP] = (v850_reg_t)frame;
333         /* Signal handler args:  */
334         regs->gpr[GPR_ARG0] = signal; /* arg 0: signum */
335         regs->gpr[GPR_ARG1] = (v850_reg_t)&frame->sc;/* arg 1: sigcontext */
336
337         set_fs(USER_DS);
338
339 #if DEBUG_SIG
340         printk("SIG deliver (%s:%d): sp=%p pc=%08lx ra=%08lx\n",
341                 current->comm, current->pid, frame, regs->pc, );
342 #endif
343
344         return;
345
346 give_sigsegv:
347         force_sigsegv(sig, current);
348 }
349
350 static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
351                            sigset_t *set, struct pt_regs *regs)
352 {
353         struct rt_sigframe *frame;
354         int err = 0;
355         int signal;
356
357         frame = get_sigframe(ka, regs, sizeof(*frame));
358
359         if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
360                 goto give_sigsegv;
361
362         signal = current_thread_info()->exec_domain
363                 && current_thread_info()->exec_domain->signal_invmap
364                 && sig < 32
365                 ? current_thread_info()->exec_domain->signal_invmap[sig]
366                 : sig;
367
368         err |= copy_siginfo_to_user(&frame->info, info);
369
370         /* Create the ucontext.  */
371         err |= __put_user(0, &frame->uc.uc_flags);
372         err |= __put_user(0, &frame->uc.uc_link);
373         err |= __put_user((void *)current->sas_ss_sp,
374                           &frame->uc.uc_stack.ss_sp);
375         err |= __put_user(sas_ss_flags(regs->gpr[GPR_SP]),
376                           &frame->uc.uc_stack.ss_flags);
377         err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
378         err |= setup_sigcontext(&frame->uc.uc_mcontext,
379                                 regs, set->sig[0]);
380         err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
381
382         /* Set up to return from userspace.  If provided, use a stub
383            already in userspace.  */
384         if (ka->sa.sa_flags & SA_RESTORER) {
385                 regs->gpr[GPR_LP] = (unsigned long) ka->sa.sa_restorer;
386         } else {
387                 /* Note, these encodings are _little endian_!  */
388
389                 /* addi  __NR_sigreturn, r0, r12  */
390                 err |= __put_user(0x6600 | (__NR_sigreturn << 16),
391                                   frame->tramp + 0);
392                 /* trap 0 */
393                 err |= __put_user(0x010007e0,
394                                   frame->tramp + 1);
395
396                 regs->gpr[GPR_LP] = (unsigned long)frame->tramp;
397
398                 flush_cache_sigtramp (regs->gpr[GPR_LP]);
399         }
400
401         if (err)
402                 goto give_sigsegv;
403
404         /* Set up registers for signal handler.  */
405         regs->pc = (v850_reg_t) ka->sa.sa_handler;
406         regs->gpr[GPR_SP] = (v850_reg_t)frame;
407         /* Signal handler args:  */
408         regs->gpr[GPR_ARG0] = signal; /* arg 0: signum */
409         regs->gpr[GPR_ARG1] = (v850_reg_t)&frame->info; /* arg 1: siginfo */
410         regs->gpr[GPR_ARG2] = (v850_reg_t)&frame->uc; /* arg 2: ucontext */
411
412         set_fs(USER_DS);
413
414 #if DEBUG_SIG
415         printk("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
416                 current->comm, current->pid, frame, regs->pc, regs->pr);
417 #endif
418
419         return;
420
421 give_sigsegv:
422         force_sigsegv(sig, current);
423 }
424
425 /*
426  * OK, we're invoking a handler
427  */     
428
429 static void
430 handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
431               sigset_t *oldset, struct pt_regs * regs)
432 {
433         /* Are we from a system call? */
434         if (PT_REGS_SYSCALL (regs)) {
435                 /* If so, check system call restarting.. */
436                 switch (regs->gpr[GPR_RVAL]) {
437                 case -ERESTART_RESTARTBLOCK:
438                         current_thread_info()->restart_block.fn =
439                                 do_no_restart_syscall;
440                         /* fall through */
441                 case -ERESTARTNOHAND:
442                         regs->gpr[GPR_RVAL] = -EINTR;
443                         break;
444
445                 case -ERESTARTSYS:
446                         if (!(ka->sa.sa_flags & SA_RESTART)) {
447                                 regs->gpr[GPR_RVAL] = -EINTR;
448                                 break;
449                         }
450                         /* fallthrough */
451                 case -ERESTARTNOINTR:
452                         regs->gpr[12] = PT_REGS_SYSCALL (regs);
453                         regs->pc -= 4; /* Size of `trap 0' insn.  */
454                 }
455
456                 PT_REGS_SET_SYSCALL (regs, 0);
457         }
458
459         /* Set up the stack frame */
460         if (ka->sa.sa_flags & SA_SIGINFO)
461                 setup_rt_frame(sig, ka, info, oldset, regs);
462         else
463                 setup_frame(sig, ka, oldset, regs);
464
465         spin_lock_irq(&current->sighand->siglock);
466         sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
467         if (!(ka->sa.sa_flags & SA_NODEFER))
468                 sigaddset(&current->blocked,sig);
469         recalc_sigpending();
470         spin_unlock_irq(&current->sighand->siglock);
471 }
472
473 /*
474  * Note that 'init' is a special process: it doesn't get signals it doesn't
475  * want to handle. Thus you cannot kill init even with a SIGKILL even by
476  * mistake.
477  *
478  * Note that we go through the signals twice: once to check the signals that
479  * the kernel can handle, and then we build all the user-level signal handling
480  * stack-frames in one go after that.
481  */
482 int do_signal(struct pt_regs *regs, sigset_t *oldset)
483 {
484         siginfo_t info;
485         int signr;
486         struct k_sigaction ka;
487
488         /*
489          * We want the common case to go fast, which
490          * is why we may in certain cases get here from
491          * kernel mode. Just return without doing anything
492          * if so.
493          */
494         if (!user_mode(regs))
495                 return 1;
496
497         if (!oldset)
498                 oldset = &current->blocked;
499
500         signr = get_signal_to_deliver(&info, &ka, regs, NULL);
501         if (signr > 0) {
502                 /* Whee!  Actually deliver the signal.  */
503                 handle_signal(signr, &info, &ka, oldset, regs);
504                 return 1;
505         }
506
507         /* Did we come from a system call? */
508         if (PT_REGS_SYSCALL (regs)) {
509                 int rval = (int)regs->gpr[GPR_RVAL];
510                 /* Restart the system call - no handlers present */
511                 if (rval == -ERESTARTNOHAND
512                     || rval == -ERESTARTSYS
513                     || rval == -ERESTARTNOINTR)
514                 {
515                         regs->gpr[12] = PT_REGS_SYSCALL (regs);
516                         regs->pc -= 4; /* Size of `trap 0' insn.  */
517                 }
518                 else if (rval == -ERESTART_RESTARTBLOCK) {
519                         regs->gpr[12] = __NR_restart_syscall;
520                         regs->pc -= 4; /* Size of `trap 0' insn.  */
521                 }
522         }
523         return 0;
524 }