This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.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 (verify_area(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 (verify_area(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 (verify_area(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         stack_t st;
229         int gr8;
230
231         if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
232                 goto badframe;
233         if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
234                 goto badframe;
235
236         sigdelsetmask(&set, ~_BLOCKABLE);
237         spin_lock_irq(&current->sighand->siglock);
238         current->blocked = set;
239         recalc_sigpending();
240         spin_unlock_irq(&current->sighand->siglock);
241
242         if (restore_sigcontext(&frame->uc.uc_mcontext, &gr8))
243                 goto badframe;
244
245         if (do_sigaltstack(&frame->uc.uc_stack, NULL, __frame->sp) == -EFAULT)
246                 goto badframe;
247
248         return gr8;
249
250 badframe:
251         force_sig(SIGSEGV, current);
252         return 0;
253 }
254
255 /*
256  * Set up a signal frame
257  */
258 static int setup_sigcontext(struct sigcontext __user *sc, unsigned long mask)
259 {
260         save_user_regs(current->thread.user);
261
262         if (copy_to_user(&sc->sc_context, current->thread.user, sizeof(sc->sc_context)) != 0)
263                 goto badframe;
264
265         /* non-iBCS2 extensions.. */
266         if (__put_user(mask, &sc->sc_oldmask) < 0)
267                 goto badframe;
268
269         return 0;
270
271  badframe:
272         return 1;
273 }
274
275 /*****************************************************************************/
276 /*
277  * Determine which stack to use..
278  */
279 static inline void __user *get_sigframe(struct k_sigaction *ka,
280                                         struct pt_regs *regs,
281                                         size_t frame_size)
282 {
283         unsigned long sp;
284
285         /* Default to using normal stack */
286         sp = regs->sp;
287
288         /* This is the X/Open sanctioned signal stack switching.  */
289         if (ka->sa.sa_flags & SA_ONSTACK) {
290                 if (! on_sig_stack(sp))
291                         sp = current->sas_ss_sp + current->sas_ss_size;
292         }
293
294         return (void __user *) ((sp - frame_size) & ~7UL);
295 } /* end get_sigframe() */
296
297 /*****************************************************************************/
298 /*
299  *
300  */
301 static void setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs * regs)
302 {
303         struct sigframe __user *frame;
304         int rsig;
305
306         frame = get_sigframe(ka, regs, sizeof(*frame));
307
308         if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
309                 goto give_sigsegv;
310
311         rsig = sig;
312         if (sig < 32 &&
313             __current_thread_info->exec_domain &&
314             __current_thread_info->exec_domain->signal_invmap)
315                 rsig = __current_thread_info->exec_domain->signal_invmap[sig];
316
317         if (__put_user(rsig, &frame->sig) < 0)
318                 goto give_sigsegv;
319
320         if (setup_sigcontext(&frame->sc, set->sig[0]))
321                 goto give_sigsegv;
322
323         if (_NSIG_WORDS > 1) {
324                 if (__copy_to_user(frame->extramask, &set->sig[1],
325                                    sizeof(frame->extramask)))
326                         goto give_sigsegv;
327         }
328
329         /* Set up to return from userspace.  If provided, use a stub
330          * already in userspace.  */
331         if (ka->sa.sa_flags & SA_RESTORER) {
332                 if (__put_user(ka->sa.sa_restorer, &frame->pretcode) < 0)
333                         goto give_sigsegv;
334         }
335         else {
336                 /* Set up the following code on the stack:
337                  *      setlos  #__NR_sigreturn,gr7
338                  *      tira    gr0,0
339                  */
340                 if (__put_user((void (*)(void))frame->retcode, &frame->pretcode) ||
341                     __put_user(0x8efc0000|__NR_sigreturn, &frame->retcode[0]) ||
342                     __put_user(0xc0700000, &frame->retcode[1]))
343                         goto give_sigsegv;
344
345                 flush_icache_range((unsigned long) frame->retcode,
346                                    (unsigned long) (frame->retcode + 2));
347         }
348
349         /* set up registers for signal handler */
350         regs->sp   = (unsigned long) frame;
351         regs->lr   = (unsigned long) &frame->retcode;
352         regs->gr8  = sig;
353
354         if (get_personality & FDPIC_FUNCPTRS) {
355                 struct fdpic_func_descriptor __user *funcptr =
356                         (struct fdpic_func_descriptor *) ka->sa.sa_handler;
357                 __get_user(regs->pc, &funcptr->text);
358                 __get_user(regs->gr15, &funcptr->GOT);
359         } else {
360                 regs->pc   = (unsigned long) ka->sa.sa_handler;
361                 regs->gr15 = 0;
362         }
363
364         set_fs(USER_DS);
365
366 #if DEBUG_SIG
367         printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
368                 sig, current->comm, current->pid, frame, regs->pc, frame->pretcode);
369 #endif
370
371         return;
372
373 give_sigsegv:
374         if (sig == SIGSEGV)
375                 ka->sa.sa_handler = SIG_DFL;
376
377         force_sig(SIGSEGV, current);
378 } /* end setup_frame() */
379
380 /*****************************************************************************/
381 /*
382  *
383  */
384 static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
385                            sigset_t *set, struct pt_regs * regs)
386 {
387         struct rt_sigframe __user *frame;
388         int rsig;
389
390         frame = get_sigframe(ka, regs, sizeof(*frame));
391
392         if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
393                 goto give_sigsegv;
394
395         rsig = sig;
396         if (sig < 32 &&
397             __current_thread_info->exec_domain &&
398             __current_thread_info->exec_domain->signal_invmap)
399                 rsig = __current_thread_info->exec_domain->signal_invmap[sig];
400
401         if (__put_user(rsig,            &frame->sig) ||
402             __put_user(&frame->info,    &frame->pinfo) ||
403             __put_user(&frame->uc,      &frame->puc))
404                 goto give_sigsegv;
405
406         if (copy_siginfo_to_user(&frame->info, info))
407                 goto give_sigsegv;
408
409         /* Create the ucontext.  */
410         if (__put_user(0, &frame->uc.uc_flags) ||
411             __put_user(0, &frame->uc.uc_link) ||
412             __put_user((void*)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) ||
413             __put_user(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags) ||
414             __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size))
415                 goto give_sigsegv;
416
417         if (setup_sigcontext(&frame->uc.uc_mcontext, set->sig[0]))
418                 goto give_sigsegv;
419
420         if (__copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)))
421                 goto give_sigsegv;
422
423         /* Set up to return from userspace.  If provided, use a stub
424          * already in userspace.  */
425         if (ka->sa.sa_flags & SA_RESTORER) {
426                 if (__put_user(ka->sa.sa_restorer, &frame->pretcode))
427                         goto give_sigsegv;
428         }
429         else {
430                 /* Set up the following code on the stack:
431                  *      setlos  #__NR_sigreturn,gr7
432                  *      tira    gr0,0
433                  */
434                 if (__put_user((void (*)(void))frame->retcode, &frame->pretcode) ||
435                     __put_user(0x8efc0000|__NR_rt_sigreturn, &frame->retcode[0]) ||
436                     __put_user(0xc0700000, &frame->retcode[1]))
437                         goto give_sigsegv;
438
439                 flush_icache_range((unsigned long) frame->retcode,
440                                    (unsigned long) (frame->retcode + 2));
441         }
442
443         /* Set up registers for signal handler */
444         regs->sp  = (unsigned long) frame;
445         regs->lr   = (unsigned long) &frame->retcode;
446         regs->gr8 = sig;
447         regs->gr9 = (unsigned long) &frame->info;
448
449         if (get_personality & FDPIC_FUNCPTRS) {
450                 struct fdpic_func_descriptor *funcptr =
451                         (struct fdpic_func_descriptor __user *) ka->sa.sa_handler;
452                 __get_user(regs->pc, &funcptr->text);
453                 __get_user(regs->gr15, &funcptr->GOT);
454         } else {
455                 regs->pc   = (unsigned long) ka->sa.sa_handler;
456                 regs->gr15 = 0;
457         }
458
459         set_fs(USER_DS);
460
461 #if DEBUG_SIG
462         printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
463                 sig, current->comm, current->pid, frame, regs->pc, frame->pretcode);
464 #endif
465
466         return;
467
468 give_sigsegv:
469         if (sig == SIGSEGV)
470                 ka->sa.sa_handler = SIG_DFL;
471         force_sig(SIGSEGV, current);
472
473 } /* end setup_rt_frame() */
474
475 /*****************************************************************************/
476 /*
477  * OK, we're invoking a handler
478  */
479 static void handle_signal(unsigned long sig, siginfo_t *info,
480                           struct k_sigaction *ka, sigset_t *oldset,
481                           struct pt_regs *regs)
482 {
483         /* Are we from a system call? */
484         if (in_syscall(regs)) {
485                 /* If so, check system call restarting.. */
486                 switch (regs->gr8) {
487                 case -ERESTART_RESTARTBLOCK:
488                 case -ERESTARTNOHAND:
489                         regs->gr8 = -EINTR;
490                         break;
491
492                 case -ERESTARTSYS:
493                         if (!(ka->sa.sa_flags & SA_RESTART)) {
494                                 regs->gr8 = -EINTR;
495                                 break;
496                         }
497                         /* fallthrough */
498                 case -ERESTARTNOINTR:
499                         regs->gr8 = regs->orig_gr8;
500                         regs->pc -= 4;
501                 }
502         }
503
504         /* Set up the stack frame */
505         if (ka->sa.sa_flags & SA_SIGINFO)
506                 setup_rt_frame(sig, ka, info, oldset, regs);
507         else
508                 setup_frame(sig, ka, oldset, regs);
509
510         if (!(ka->sa.sa_flags & SA_NODEFER)) {
511                 spin_lock_irq(&current->sighand->siglock);
512                 sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
513                 sigaddset(&current->blocked, sig);
514                 recalc_sigpending();
515                 spin_unlock_irq(&current->sighand->siglock);
516         }
517 } /* end handle_signal() */
518
519 /*****************************************************************************/
520 /*
521  * Note that 'init' is a special process: it doesn't get signals it doesn't
522  * want to handle. Thus you cannot kill init even with a SIGKILL even by
523  * mistake.
524  */
525 int do_signal(struct pt_regs *regs, sigset_t *oldset)
526 {
527         struct k_sigaction ka;
528         siginfo_t info;
529         int signr;
530
531         /*
532          * We want the common case to go fast, which
533          * is why we may in certain cases get here from
534          * kernel mode. Just return without doing anything
535          * if so.
536          */
537         if (!user_mode(regs))
538                 return 1;
539
540         if (current->flags & PF_FREEZE) {
541                 refrigerator(0);
542                 goto no_signal;
543         }
544
545         if (!oldset)
546                 oldset = &current->blocked;
547
548         signr = get_signal_to_deliver(&info, &ka, regs, NULL);
549         if (signr > 0) {
550                 handle_signal(signr, &info, &ka, oldset, regs);
551                 return 1;
552         }
553
554  no_signal:
555         /* Did we come from a system call? */
556         if (regs->syscallno >= 0) {
557                 /* Restart the system call - no handlers present */
558                 if (regs->gr8 == -ERESTARTNOHAND ||
559                     regs->gr8 == -ERESTARTSYS ||
560                     regs->gr8 == -ERESTARTNOINTR) {
561                         regs->gr8 = regs->orig_gr8;
562                         regs->pc -= 4;
563                 }
564
565                 if (regs->gr8 == -ERESTART_RESTARTBLOCK){
566                         regs->gr8 = __NR_restart_syscall;
567                         regs->pc -= 4;
568                 }
569         }
570
571         return 0;
572 } /* end do_signal() */
573
574 /*****************************************************************************/
575 /*
576  * notification of userspace execution resumption
577  * - triggered by current->work.notify_resume
578  */
579 asmlinkage void do_notify_resume(__u32 thread_info_flags)
580 {
581         /* pending single-step? */
582         if (thread_info_flags & _TIF_SINGLESTEP)
583                 clear_thread_flag(TIF_SINGLESTEP);
584
585         /* deal with pending signal delivery */
586         if (thread_info_flags & _TIF_SIGPENDING)
587                 do_signal(__frame, NULL);
588
589 } /* end do_notify_resume() */