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