Linux-2.6.12-rc2
[pandora-kernel.git] / arch / frv / kernel / signal.c
1 /* signal.c: FRV specific bits of signal handling
2  *
3  * Copyright (C) 2003-5 Red Hat, Inc. All Rights Reserved.
4  * Written by David Howells (dhowells@redhat.com)
5  * - Derived from arch/m68k/kernel/signal.c
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version
10  * 2 of the License, or (at your option) any later version.
11  */
12
13 #include <linux/sched.h>
14 #include <linux/mm.h>
15 #include <linux/smp.h>
16 #include <linux/smp_lock.h>
17 #include <linux/kernel.h>
18 #include <linux/signal.h>
19 #include <linux/errno.h>
20 #include <linux/wait.h>
21 #include <linux/ptrace.h>
22 #include <linux/unistd.h>
23 #include <linux/personality.h>
24 #include <linux/suspend.h>
25 #include <asm/ucontext.h>
26 #include <asm/uaccess.h>
27 #include <asm/cacheflush.h>
28
29 #define DEBUG_SIG 0
30
31 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
32
33 struct fdpic_func_descriptor {
34         unsigned long   text;
35         unsigned long   GOT;
36 };
37
38 asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
39
40 /*
41  * Atomically swap in the new signal mask, and wait for a signal.
42  */
43 asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask)
44 {
45         sigset_t saveset;
46
47         mask &= _BLOCKABLE;
48         spin_lock_irq(&current->sighand->siglock);
49         saveset = current->blocked;
50         siginitset(&current->blocked, mask);
51         recalc_sigpending();
52         spin_unlock_irq(&current->sighand->siglock);
53
54         __frame->gr8 = -EINTR;
55         while (1) {
56                 current->state = TASK_INTERRUPTIBLE;
57                 schedule();
58                 if (do_signal(__frame, &saveset))
59                         /* return the signal number as the return value of this function
60                          * - this is an utterly evil hack. syscalls should not invoke do_signal()
61                          *   as entry.S sets regs->gr8 to the return value of the system call
62                          * - we can't just use sigpending() as we'd have to discard SIG_IGN signals
63                          *   and call waitpid() if SIGCHLD needed discarding
64                          * - this only works on the i386 because it passes arguments to the signal
65                          *   handler on the stack, and the return value in EAX is effectively
66                          *   discarded
67                          */
68                         return __frame->gr8;
69         }
70 }
71
72 asmlinkage int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
73 {
74         sigset_t saveset, newset;
75
76         /* XXX: Don't preclude handling different sized sigset_t's.  */
77         if (sigsetsize != sizeof(sigset_t))
78                 return -EINVAL;
79
80         if (copy_from_user(&newset, unewset, sizeof(newset)))
81                 return -EFAULT;
82         sigdelsetmask(&newset, ~_BLOCKABLE);
83
84         spin_lock_irq(&current->sighand->siglock);
85         saveset = current->blocked;
86         current->blocked = newset;
87         recalc_sigpending();
88         spin_unlock_irq(&current->sighand->siglock);
89
90         __frame->gr8 = -EINTR;
91         while (1) {
92                 current->state = TASK_INTERRUPTIBLE;
93                 schedule();
94                 if (do_signal(__frame, &saveset))
95                         /* return the signal number as the return value of this function
96                          * - this is an utterly evil hack. syscalls should not invoke do_signal()
97                          *   as entry.S sets regs->gr8 to the return value of the system call
98                          * - we can't just use sigpending() as we'd have to discard SIG_IGN signals
99                          *   and call waitpid() if SIGCHLD needed discarding
100                          * - this only works on the i386 because it passes arguments to the signal
101                          *   handler on the stack, and the return value in EAX is effectively
102                          *   discarded
103                          */
104                         return __frame->gr8;
105         }
106 }
107
108 asmlinkage int sys_sigaction(int sig,
109                              const struct old_sigaction __user *act,
110                              struct old_sigaction __user *oact)
111 {
112         struct k_sigaction new_ka, old_ka;
113         int ret;
114
115         if (act) {
116                 old_sigset_t mask;
117                 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
118                     __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
119                     __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
120                         return -EFAULT;
121                 __get_user(new_ka.sa.sa_flags, &act->sa_flags);
122                 __get_user(mask, &act->sa_mask);
123                 siginitset(&new_ka.sa.sa_mask, mask);
124         }
125
126         ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
127
128         if (!ret && oact) {
129                 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
130                     __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
131                     __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
132                         return -EFAULT;
133                 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
134                 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
135         }
136
137         return ret;
138 }
139
140 asmlinkage
141 int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
142 {
143         return do_sigaltstack(uss, uoss, __frame->sp);
144 }
145
146
147 /*
148  * Do a signal return; undo the signal stack.
149  */
150
151 struct sigframe
152 {
153         void (*pretcode)(void);
154         int sig;
155         struct sigcontext sc;
156         unsigned long extramask[_NSIG_WORDS-1];
157         uint32_t retcode[2];
158 };
159
160 struct rt_sigframe
161 {
162         void (*pretcode)(void);
163         int sig;
164         struct siginfo *pinfo;
165         void *puc;
166         struct siginfo info;
167         struct ucontext uc;
168         uint32_t retcode[2];
169 };
170
171 static int restore_sigcontext(struct sigcontext __user *sc, int *_gr8)
172 {
173         struct user_context *user = current->thread.user;
174         unsigned long tbr, psr;
175
176         tbr = user->i.tbr;
177         psr = user->i.psr;
178         if (copy_from_user(user, &sc->sc_context, sizeof(sc->sc_context)))
179                 goto badframe;
180         user->i.tbr = tbr;
181         user->i.psr = psr;
182
183         restore_user_regs(user);
184
185         user->i.syscallno = -1;         /* disable syscall checks */
186
187         *_gr8 = user->i.gr[8];
188         return 0;
189
190  badframe:
191         return 1;
192 }
193
194 asmlinkage int sys_sigreturn(void)
195 {
196         struct sigframe __user *frame = (struct sigframe __user *) __frame->sp;
197         sigset_t set;
198         int gr8;
199
200         if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
201                 goto badframe;
202         if (__get_user(set.sig[0], &frame->sc.sc_oldmask))
203                 goto badframe;
204
205         if (_NSIG_WORDS > 1 &&
206             __copy_from_user(&set.sig[1], &frame->extramask, sizeof(frame->extramask)))
207                 goto badframe;
208
209         sigdelsetmask(&set, ~_BLOCKABLE);
210         spin_lock_irq(&current->sighand->siglock);
211         current->blocked = set;
212         recalc_sigpending();
213         spin_unlock_irq(&current->sighand->siglock);
214
215         if (restore_sigcontext(&frame->sc, &gr8))
216                 goto badframe;
217         return gr8;
218
219  badframe:
220         force_sig(SIGSEGV, current);
221         return 0;
222 }
223
224 asmlinkage int sys_rt_sigreturn(void)
225 {
226         struct rt_sigframe __user *frame = (struct rt_sigframe __user *) __frame->sp;
227         sigset_t set;
228         int gr8;
229
230         if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
231                 goto badframe;
232         if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
233                 goto badframe;
234
235         sigdelsetmask(&set, ~_BLOCKABLE);
236         spin_lock_irq(&current->sighand->siglock);
237         current->blocked = set;
238         recalc_sigpending();
239         spin_unlock_irq(&current->sighand->siglock);
240
241         if (restore_sigcontext(&frame->uc.uc_mcontext, &gr8))
242                 goto badframe;
243
244         if (do_sigaltstack(&frame->uc.uc_stack, NULL, __frame->sp) == -EFAULT)
245                 goto badframe;
246
247         return gr8;
248
249 badframe:
250         force_sig(SIGSEGV, current);
251         return 0;
252 }
253
254 /*
255  * Set up a signal frame
256  */
257 static int setup_sigcontext(struct sigcontext __user *sc, unsigned long mask)
258 {
259         save_user_regs(current->thread.user);
260
261         if (copy_to_user(&sc->sc_context, current->thread.user, sizeof(sc->sc_context)) != 0)
262                 goto badframe;
263
264         /* non-iBCS2 extensions.. */
265         if (__put_user(mask, &sc->sc_oldmask) < 0)
266                 goto badframe;
267
268         return 0;
269
270  badframe:
271         return 1;
272 }
273
274 /*****************************************************************************/
275 /*
276  * Determine which stack to use..
277  */
278 static inline void __user *get_sigframe(struct k_sigaction *ka,
279                                         struct pt_regs *regs,
280                                         size_t frame_size)
281 {
282         unsigned long sp;
283
284         /* Default to using normal stack */
285         sp = regs->sp;
286
287         /* This is the X/Open sanctioned signal stack switching.  */
288         if (ka->sa.sa_flags & SA_ONSTACK) {
289                 if (! on_sig_stack(sp))
290                         sp = current->sas_ss_sp + current->sas_ss_size;
291         }
292
293         return (void __user *) ((sp - frame_size) & ~7UL);
294 } /* end get_sigframe() */
295
296 /*****************************************************************************/
297 /*
298  *
299  */
300 static void setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs * regs)
301 {
302         struct sigframe __user *frame;
303         int rsig;
304
305         frame = get_sigframe(ka, regs, sizeof(*frame));
306
307         if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
308                 goto give_sigsegv;
309
310         rsig = sig;
311         if (sig < 32 &&
312             __current_thread_info->exec_domain &&
313             __current_thread_info->exec_domain->signal_invmap)
314                 rsig = __current_thread_info->exec_domain->signal_invmap[sig];
315
316         if (__put_user(rsig, &frame->sig) < 0)
317                 goto give_sigsegv;
318
319         if (setup_sigcontext(&frame->sc, set->sig[0]))
320                 goto give_sigsegv;
321
322         if (_NSIG_WORDS > 1) {
323                 if (__copy_to_user(frame->extramask, &set->sig[1],
324                                    sizeof(frame->extramask)))
325                         goto give_sigsegv;
326         }
327
328         /* Set up to return from userspace.  If provided, use a stub
329          * already in userspace.  */
330         if (ka->sa.sa_flags & SA_RESTORER) {
331                 if (__put_user(ka->sa.sa_restorer, &frame->pretcode) < 0)
332                         goto give_sigsegv;
333         }
334         else {
335                 /* Set up the following code on the stack:
336                  *      setlos  #__NR_sigreturn,gr7
337                  *      tira    gr0,0
338                  */
339                 if (__put_user((void (*)(void))frame->retcode, &frame->pretcode) ||
340                     __put_user(0x8efc0000|__NR_sigreturn, &frame->retcode[0]) ||
341                     __put_user(0xc0700000, &frame->retcode[1]))
342                         goto give_sigsegv;
343
344                 flush_icache_range((unsigned long) frame->retcode,
345                                    (unsigned long) (frame->retcode + 2));
346         }
347
348         /* set up registers for signal handler */
349         regs->sp   = (unsigned long) frame;
350         regs->lr   = (unsigned long) &frame->retcode;
351         regs->gr8  = sig;
352
353         if (get_personality & FDPIC_FUNCPTRS) {
354                 struct fdpic_func_descriptor __user *funcptr =
355                         (struct fdpic_func_descriptor *) ka->sa.sa_handler;
356                 __get_user(regs->pc, &funcptr->text);
357                 __get_user(regs->gr15, &funcptr->GOT);
358         } else {
359                 regs->pc   = (unsigned long) ka->sa.sa_handler;
360                 regs->gr15 = 0;
361         }
362
363         set_fs(USER_DS);
364
365 #if DEBUG_SIG
366         printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
367                 sig, current->comm, current->pid, frame, regs->pc, frame->pretcode);
368 #endif
369
370         return;
371
372 give_sigsegv:
373         if (sig == SIGSEGV)
374                 ka->sa.sa_handler = SIG_DFL;
375
376         force_sig(SIGSEGV, current);
377 } /* end setup_frame() */
378
379 /*****************************************************************************/
380 /*
381  *
382  */
383 static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
384                            sigset_t *set, struct pt_regs * regs)
385 {
386         struct rt_sigframe __user *frame;
387         int rsig;
388
389         frame = get_sigframe(ka, regs, sizeof(*frame));
390
391         if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
392                 goto give_sigsegv;
393
394         rsig = sig;
395         if (sig < 32 &&
396             __current_thread_info->exec_domain &&
397             __current_thread_info->exec_domain->signal_invmap)
398                 rsig = __current_thread_info->exec_domain->signal_invmap[sig];
399
400         if (__put_user(rsig,            &frame->sig) ||
401             __put_user(&frame->info,    &frame->pinfo) ||
402             __put_user(&frame->uc,      &frame->puc))
403                 goto give_sigsegv;
404
405         if (copy_siginfo_to_user(&frame->info, info))
406                 goto give_sigsegv;
407
408         /* Create the ucontext.  */
409         if (__put_user(0, &frame->uc.uc_flags) ||
410             __put_user(0, &frame->uc.uc_link) ||
411             __put_user((void*)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) ||
412             __put_user(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags) ||
413             __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size))
414                 goto give_sigsegv;
415
416         if (setup_sigcontext(&frame->uc.uc_mcontext, set->sig[0]))
417                 goto give_sigsegv;
418
419         if (__copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)))
420                 goto give_sigsegv;
421
422         /* Set up to return from userspace.  If provided, use a stub
423          * already in userspace.  */
424         if (ka->sa.sa_flags & SA_RESTORER) {
425                 if (__put_user(ka->sa.sa_restorer, &frame->pretcode))
426                         goto give_sigsegv;
427         }
428         else {
429                 /* Set up the following code on the stack:
430                  *      setlos  #__NR_sigreturn,gr7
431                  *      tira    gr0,0
432                  */
433                 if (__put_user((void (*)(void))frame->retcode, &frame->pretcode) ||
434                     __put_user(0x8efc0000|__NR_rt_sigreturn, &frame->retcode[0]) ||
435                     __put_user(0xc0700000, &frame->retcode[1]))
436                         goto give_sigsegv;
437
438                 flush_icache_range((unsigned long) frame->retcode,
439                                    (unsigned long) (frame->retcode + 2));
440         }
441
442         /* Set up registers for signal handler */
443         regs->sp  = (unsigned long) frame;
444         regs->lr   = (unsigned long) &frame->retcode;
445         regs->gr8 = sig;
446         regs->gr9 = (unsigned long) &frame->info;
447
448         if (get_personality & FDPIC_FUNCPTRS) {
449                 struct fdpic_func_descriptor *funcptr =
450                         (struct fdpic_func_descriptor __user *) ka->sa.sa_handler;
451                 __get_user(regs->pc, &funcptr->text);
452                 __get_user(regs->gr15, &funcptr->GOT);
453         } else {
454                 regs->pc   = (unsigned long) ka->sa.sa_handler;
455                 regs->gr15 = 0;
456         }
457
458         set_fs(USER_DS);
459
460 #if DEBUG_SIG
461         printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
462                 sig, current->comm, current->pid, frame, regs->pc, frame->pretcode);
463 #endif
464
465         return;
466
467 give_sigsegv:
468         if (sig == SIGSEGV)
469                 ka->sa.sa_handler = SIG_DFL;
470         force_sig(SIGSEGV, current);
471
472 } /* end setup_rt_frame() */
473
474 /*****************************************************************************/
475 /*
476  * OK, we're invoking a handler
477  */
478 static void handle_signal(unsigned long sig, siginfo_t *info,
479                           struct k_sigaction *ka, sigset_t *oldset,
480                           struct pt_regs *regs)
481 {
482         /* Are we from a system call? */
483         if (in_syscall(regs)) {
484                 /* If so, check system call restarting.. */
485                 switch (regs->gr8) {
486                 case -ERESTART_RESTARTBLOCK:
487                 case -ERESTARTNOHAND:
488                         regs->gr8 = -EINTR;
489                         break;
490
491                 case -ERESTARTSYS:
492                         if (!(ka->sa.sa_flags & SA_RESTART)) {
493                                 regs->gr8 = -EINTR;
494                                 break;
495                         }
496                         /* fallthrough */
497                 case -ERESTARTNOINTR:
498                         regs->gr8 = regs->orig_gr8;
499                         regs->pc -= 4;
500                 }
501         }
502
503         /* Set up the stack frame */
504         if (ka->sa.sa_flags & SA_SIGINFO)
505                 setup_rt_frame(sig, ka, info, oldset, regs);
506         else
507                 setup_frame(sig, ka, oldset, regs);
508
509         if (!(ka->sa.sa_flags & SA_NODEFER)) {
510                 spin_lock_irq(&current->sighand->siglock);
511                 sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
512                 sigaddset(&current->blocked, sig);
513                 recalc_sigpending();
514                 spin_unlock_irq(&current->sighand->siglock);
515         }
516 } /* end handle_signal() */
517
518 /*****************************************************************************/
519 /*
520  * Note that 'init' is a special process: it doesn't get signals it doesn't
521  * want to handle. Thus you cannot kill init even with a SIGKILL even by
522  * mistake.
523  */
524 int do_signal(struct pt_regs *regs, sigset_t *oldset)
525 {
526         struct k_sigaction ka;
527         siginfo_t info;
528         int signr;
529
530         /*
531          * We want the common case to go fast, which
532          * is why we may in certain cases get here from
533          * kernel mode. Just return without doing anything
534          * if so.
535          */
536         if (!user_mode(regs))
537                 return 1;
538
539         if (current->flags & PF_FREEZE) {
540                 refrigerator(0);
541                 goto no_signal;
542         }
543
544         if (!oldset)
545                 oldset = &current->blocked;
546
547         signr = get_signal_to_deliver(&info, &ka, regs, NULL);
548         if (signr > 0) {
549                 handle_signal(signr, &info, &ka, oldset, regs);
550                 return 1;
551         }
552
553  no_signal:
554         /* Did we come from a system call? */
555         if (regs->syscallno >= 0) {
556                 /* Restart the system call - no handlers present */
557                 if (regs->gr8 == -ERESTARTNOHAND ||
558                     regs->gr8 == -ERESTARTSYS ||
559                     regs->gr8 == -ERESTARTNOINTR) {
560                         regs->gr8 = regs->orig_gr8;
561                         regs->pc -= 4;
562                 }
563
564                 if (regs->gr8 == -ERESTART_RESTARTBLOCK){
565                         regs->gr8 = __NR_restart_syscall;
566                         regs->pc -= 4;
567                 }
568         }
569
570         return 0;
571 } /* end do_signal() */
572
573 /*****************************************************************************/
574 /*
575  * notification of userspace execution resumption
576  * - triggered by current->work.notify_resume
577  */
578 asmlinkage void do_notify_resume(__u32 thread_info_flags)
579 {
580         /* pending single-step? */
581         if (thread_info_flags & _TIF_SINGLESTEP)
582                 clear_thread_flag(TIF_SINGLESTEP);
583
584         /* deal with pending signal delivery */
585         if (thread_info_flags & _TIF_SIGPENDING)
586                 do_signal(__frame, NULL);
587
588 } /* end do_notify_resume() */