Linux-2.6.12-rc2
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / arch / mips / kernel / signal32.c
blob1f3b19124c01fdeca1a01a7a79a698440136b6fa
1 /*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
6 * Copyright (C) 1991, 1992 Linus Torvalds
7 * Copyright (C) 1994 - 2000 Ralf Baechle
8 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
9 */
10 #include <linux/sched.h>
11 #include <linux/mm.h>
12 #include <linux/smp.h>
13 #include <linux/smp_lock.h>
14 #include <linux/kernel.h>
15 #include <linux/signal.h>
16 #include <linux/syscalls.h>
17 #include <linux/errno.h>
18 #include <linux/wait.h>
19 #include <linux/ptrace.h>
20 #include <linux/compat.h>
21 #include <linux/suspend.h>
22 #include <linux/compiler.h>
24 #include <asm/asm.h>
25 #include <linux/bitops.h>
26 #include <asm/cacheflush.h>
27 #include <asm/sim.h>
28 #include <asm/uaccess.h>
29 #include <asm/ucontext.h>
30 #include <asm/system.h>
31 #include <asm/fpu.h>
33 #define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3)
35 typedef struct compat_siginfo {
36 int si_signo;
37 int si_code;
38 int si_errno;
40 union {
41 int _pad[SI_PAD_SIZE32];
43 /* kill() */
44 struct {
45 compat_pid_t _pid; /* sender's pid */
46 compat_uid_t _uid; /* sender's uid */
47 } _kill;
49 /* SIGCHLD */
50 struct {
51 compat_pid_t _pid; /* which child */
52 compat_uid_t _uid; /* sender's uid */
53 int _status; /* exit code */
54 compat_clock_t _utime;
55 compat_clock_t _stime;
56 } _sigchld;
58 /* IRIX SIGCHLD */
59 struct {
60 compat_pid_t _pid; /* which child */
61 compat_clock_t _utime;
62 int _status; /* exit code */
63 compat_clock_t _stime;
64 } _irix_sigchld;
66 /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
67 struct {
68 s32 _addr; /* faulting insn/memory ref. */
69 } _sigfault;
71 /* SIGPOLL, SIGXFSZ (To do ...) */
72 struct {
73 int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
74 int _fd;
75 } _sigpoll;
77 /* POSIX.1b timers */
78 struct {
79 unsigned int _timer1;
80 unsigned int _timer2;
81 } _timer;
83 /* POSIX.1b signals */
84 struct {
85 compat_pid_t _pid; /* sender's pid */
86 compat_uid_t _uid; /* sender's uid */
87 compat_sigval_t _sigval;
88 } _rt;
90 } _sifields;
91 } compat_siginfo_t;
94 * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
96 #define __NR_O32_sigreturn 4119
97 #define __NR_O32_rt_sigreturn 4193
98 #define __NR_O32_restart_syscall 4253
100 #define DEBUG_SIG 0
102 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
104 extern int do_signal32(sigset_t *oldset, struct pt_regs *regs);
106 /* 32-bit compatibility types */
108 #define _NSIG_BPW32 32
109 #define _NSIG_WORDS32 (_NSIG / _NSIG_BPW32)
111 typedef struct {
112 unsigned int sig[_NSIG_WORDS32];
113 } sigset_t32;
115 typedef unsigned int __sighandler32_t;
116 typedef void (*vfptr_t)(void);
118 struct sigaction32 {
119 unsigned int sa_flags;
120 __sighandler32_t sa_handler;
121 compat_sigset_t sa_mask;
124 /* IRIX compatible stack_t */
125 typedef struct sigaltstack32 {
126 s32 ss_sp;
127 compat_size_t ss_size;
128 int ss_flags;
129 } stack32_t;
131 struct ucontext32 {
132 u32 uc_flags;
133 s32 uc_link;
134 stack32_t uc_stack;
135 struct sigcontext32 uc_mcontext;
136 sigset_t32 uc_sigmask; /* mask last for extensibility */
139 extern void __put_sigset_unknown_nsig(void);
140 extern void __get_sigset_unknown_nsig(void);
142 static inline int put_sigset(const sigset_t *kbuf, compat_sigset_t *ubuf)
144 int err = 0;
146 if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)))
147 return -EFAULT;
149 switch (_NSIG_WORDS) {
150 default:
151 __put_sigset_unknown_nsig();
152 case 2:
153 err |= __put_user (kbuf->sig[1] >> 32, &ubuf->sig[3]);
154 err |= __put_user (kbuf->sig[1] & 0xffffffff, &ubuf->sig[2]);
155 case 1:
156 err |= __put_user (kbuf->sig[0] >> 32, &ubuf->sig[1]);
157 err |= __put_user (kbuf->sig[0] & 0xffffffff, &ubuf->sig[0]);
160 return err;
163 static inline int get_sigset(sigset_t *kbuf, const compat_sigset_t *ubuf)
165 int err = 0;
166 unsigned long sig[4];
168 if (!access_ok(VERIFY_READ, ubuf, sizeof(*ubuf)))
169 return -EFAULT;
171 switch (_NSIG_WORDS) {
172 default:
173 __get_sigset_unknown_nsig();
174 case 2:
175 err |= __get_user (sig[3], &ubuf->sig[3]);
176 err |= __get_user (sig[2], &ubuf->sig[2]);
177 kbuf->sig[1] = sig[2] | (sig[3] << 32);
178 case 1:
179 err |= __get_user (sig[1], &ubuf->sig[1]);
180 err |= __get_user (sig[0], &ubuf->sig[0]);
181 kbuf->sig[0] = sig[0] | (sig[1] << 32);
184 return err;
188 * Atomically swap in the new signal mask, and wait for a signal.
191 save_static_function(sys32_sigsuspend);
192 __attribute_used__ noinline static int
193 _sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
195 compat_sigset_t *uset;
196 sigset_t newset, saveset;
198 uset = (compat_sigset_t *) regs.regs[4];
199 if (get_sigset(&newset, uset))
200 return -EFAULT;
201 sigdelsetmask(&newset, ~_BLOCKABLE);
203 spin_lock_irq(&current->sighand->siglock);
204 saveset = current->blocked;
205 current->blocked = newset;
206 recalc_sigpending();
207 spin_unlock_irq(&current->sighand->siglock);
209 regs.regs[2] = EINTR;
210 regs.regs[7] = 1;
211 while (1) {
212 current->state = TASK_INTERRUPTIBLE;
213 schedule();
214 if (do_signal32(&saveset, &regs))
215 return -EINTR;
219 save_static_function(sys32_rt_sigsuspend);
220 __attribute_used__ noinline static int
221 _sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
223 compat_sigset_t *uset;
224 sigset_t newset, saveset;
225 size_t sigsetsize;
227 /* XXX Don't preclude handling different sized sigset_t's. */
228 sigsetsize = regs.regs[5];
229 if (sigsetsize != sizeof(compat_sigset_t))
230 return -EINVAL;
232 uset = (compat_sigset_t *) regs.regs[4];
233 if (get_sigset(&newset, uset))
234 return -EFAULT;
235 sigdelsetmask(&newset, ~_BLOCKABLE);
237 spin_lock_irq(&current->sighand->siglock);
238 saveset = current->blocked;
239 current->blocked = newset;
240 recalc_sigpending();
241 spin_unlock_irq(&current->sighand->siglock);
243 regs.regs[2] = EINTR;
244 regs.regs[7] = 1;
245 while (1) {
246 current->state = TASK_INTERRUPTIBLE;
247 schedule();
248 if (do_signal32(&saveset, &regs))
249 return -EINTR;
253 asmlinkage int sys32_sigaction(int sig, const struct sigaction32 *act,
254 struct sigaction32 *oact)
256 struct k_sigaction new_ka, old_ka;
257 int ret;
258 int err = 0;
260 if (act) {
261 old_sigset_t mask;
263 if (!access_ok(VERIFY_READ, act, sizeof(*act)))
264 return -EFAULT;
265 err |= __get_user((u32)(u64)new_ka.sa.sa_handler,
266 &act->sa_handler);
267 err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
268 err |= __get_user(mask, &act->sa_mask.sig[0]);
269 if (err)
270 return -EFAULT;
272 siginitset(&new_ka.sa.sa_mask, mask);
275 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
277 if (!ret && oact) {
278 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
279 return -EFAULT;
280 err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
281 err |= __put_user((u32)(u64)old_ka.sa.sa_handler,
282 &oact->sa_handler);
283 err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
284 err |= __put_user(0, &oact->sa_mask.sig[1]);
285 err |= __put_user(0, &oact->sa_mask.sig[2]);
286 err |= __put_user(0, &oact->sa_mask.sig[3]);
287 if (err)
288 return -EFAULT;
291 return ret;
294 asmlinkage int sys32_sigaltstack(nabi_no_regargs struct pt_regs regs)
296 const stack32_t *uss = (const stack32_t *) regs.regs[4];
297 stack32_t *uoss = (stack32_t *) regs.regs[5];
298 unsigned long usp = regs.regs[29];
299 stack_t kss, koss;
300 int ret, err = 0;
301 mm_segment_t old_fs = get_fs();
302 s32 sp;
304 if (uss) {
305 if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
306 return -EFAULT;
307 err |= __get_user(sp, &uss->ss_sp);
308 kss.ss_sp = (void *) (long) sp;
309 err |= __get_user(kss.ss_size, &uss->ss_size);
310 err |= __get_user(kss.ss_flags, &uss->ss_flags);
311 if (err)
312 return -EFAULT;
315 set_fs (KERNEL_DS);
316 ret = do_sigaltstack(uss ? &kss : NULL , uoss ? &koss : NULL, usp);
317 set_fs (old_fs);
319 if (!ret && uoss) {
320 if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
321 return -EFAULT;
322 sp = (int) (long) koss.ss_sp;
323 err |= __put_user(sp, &uoss->ss_sp);
324 err |= __put_user(koss.ss_size, &uoss->ss_size);
325 err |= __put_user(koss.ss_flags, &uoss->ss_flags);
326 if (err)
327 return -EFAULT;
329 return ret;
332 static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 *sc)
334 int err = 0;
335 __u32 used_math;
337 /* Always make any pending restarted system calls return -EINTR */
338 current_thread_info()->restart_block.fn = do_no_restart_syscall;
340 err |= __get_user(regs->cp0_epc, &sc->sc_pc);
341 err |= __get_user(regs->hi, &sc->sc_mdhi);
342 err |= __get_user(regs->lo, &sc->sc_mdlo);
344 #define restore_gp_reg(i) do { \
345 err |= __get_user(regs->regs[i], &sc->sc_regs[i]); \
346 } while(0)
347 restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
348 restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
349 restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
350 restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
351 restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
352 restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
353 restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
354 restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
355 restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
356 restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
357 restore_gp_reg(31);
358 #undef restore_gp_reg
360 err |= __get_user(used_math, &sc->sc_used_math);
361 conditional_used_math(used_math);
363 preempt_disable();
365 if (used_math()) {
366 /* restore fpu context if we have used it before */
367 own_fpu();
368 err |= restore_fp_context32(sc);
369 } else {
370 /* signal handler may have used FPU. Give it up. */
371 lose_fpu();
374 preempt_enable();
376 return err;
379 struct sigframe {
380 u32 sf_ass[4]; /* argument save space for o32 */
381 u32 sf_code[2]; /* signal trampoline */
382 struct sigcontext32 sf_sc;
383 sigset_t sf_mask;
386 struct rt_sigframe32 {
387 u32 rs_ass[4]; /* argument save space for o32 */
388 u32 rs_code[2]; /* signal trampoline */
389 compat_siginfo_t rs_info;
390 struct ucontext32 rs_uc;
393 int copy_siginfo_to_user32(compat_siginfo_t *to, siginfo_t *from)
395 int err;
397 if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
398 return -EFAULT;
400 /* If you change siginfo_t structure, please be sure
401 this code is fixed accordingly.
402 It should never copy any pad contained in the structure
403 to avoid security leaks, but must copy the generic
404 3 ints plus the relevant union member.
405 This routine must convert siginfo from 64bit to 32bit as well
406 at the same time. */
407 err = __put_user(from->si_signo, &to->si_signo);
408 err |= __put_user(from->si_errno, &to->si_errno);
409 err |= __put_user((short)from->si_code, &to->si_code);
410 if (from->si_code < 0)
411 err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
412 else {
413 switch (from->si_code >> 16) {
414 case __SI_CHLD >> 16:
415 err |= __put_user(from->si_utime, &to->si_utime);
416 err |= __put_user(from->si_stime, &to->si_stime);
417 err |= __put_user(from->si_status, &to->si_status);
418 default:
419 err |= __put_user(from->si_pid, &to->si_pid);
420 err |= __put_user(from->si_uid, &to->si_uid);
421 break;
422 case __SI_FAULT >> 16:
423 err |= __put_user((long)from->si_addr, &to->si_addr);
424 break;
425 case __SI_POLL >> 16:
426 err |= __put_user(from->si_band, &to->si_band);
427 err |= __put_user(from->si_fd, &to->si_fd);
428 break;
429 case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
430 case __SI_MESGQ >> 16:
431 err |= __put_user(from->si_pid, &to->si_pid);
432 err |= __put_user(from->si_uid, &to->si_uid);
433 err |= __put_user(from->si_int, &to->si_int);
434 break;
437 return err;
440 save_static_function(sys32_sigreturn);
441 __attribute_used__ noinline static void
442 _sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
444 struct sigframe *frame;
445 sigset_t blocked;
447 frame = (struct sigframe *) regs.regs[29];
448 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
449 goto badframe;
450 if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked)))
451 goto badframe;
453 sigdelsetmask(&blocked, ~_BLOCKABLE);
454 spin_lock_irq(&current->sighand->siglock);
455 current->blocked = blocked;
456 recalc_sigpending();
457 spin_unlock_irq(&current->sighand->siglock);
459 if (restore_sigcontext32(&regs, &frame->sf_sc))
460 goto badframe;
463 * Don't let your children do this ...
465 if (current_thread_info()->flags & TIF_SYSCALL_TRACE)
466 do_syscall_trace(&regs, 1);
467 __asm__ __volatile__(
468 "move\t$29, %0\n\t"
469 "j\tsyscall_exit"
470 :/* no outputs */
471 :"r" (&regs));
472 /* Unreached */
474 badframe:
475 force_sig(SIGSEGV, current);
478 save_static_function(sys32_rt_sigreturn);
479 __attribute_used__ noinline static void
480 _sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
482 struct rt_sigframe32 *frame;
483 sigset_t set;
484 stack_t st;
485 s32 sp;
487 frame = (struct rt_sigframe32 *) regs.regs[29];
488 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
489 goto badframe;
490 if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
491 goto badframe;
493 sigdelsetmask(&set, ~_BLOCKABLE);
494 spin_lock_irq(&current->sighand->siglock);
495 current->blocked = set;
496 recalc_sigpending();
497 spin_unlock_irq(&current->sighand->siglock);
499 if (restore_sigcontext32(&regs, &frame->rs_uc.uc_mcontext))
500 goto badframe;
502 /* The ucontext contains a stack32_t, so we must convert! */
503 if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp))
504 goto badframe;
505 st.ss_size = (long) sp;
506 if (__get_user(st.ss_size, &frame->rs_uc.uc_stack.ss_size))
507 goto badframe;
508 if (__get_user(st.ss_flags, &frame->rs_uc.uc_stack.ss_flags))
509 goto badframe;
511 /* It is more difficult to avoid calling this function than to
512 call it and ignore errors. */
513 do_sigaltstack(&st, NULL, regs.regs[29]);
516 * Don't let your children do this ...
518 __asm__ __volatile__(
519 "move\t$29, %0\n\t"
520 "j\tsyscall_exit"
521 :/* no outputs */
522 :"r" (&regs));
523 /* Unreached */
525 badframe:
526 force_sig(SIGSEGV, current);
529 static inline int setup_sigcontext32(struct pt_regs *regs,
530 struct sigcontext32 *sc)
532 int err = 0;
534 err |= __put_user(regs->cp0_epc, &sc->sc_pc);
535 err |= __put_user(regs->cp0_status, &sc->sc_status);
537 #define save_gp_reg(i) { \
538 err |= __put_user(regs->regs[i], &sc->sc_regs[i]); \
539 } while(0)
540 __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
541 save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);
542 save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);
543 save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
544 save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18);
545 save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22);
546 save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
547 save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30);
548 save_gp_reg(31);
549 #undef save_gp_reg
551 err |= __put_user(regs->hi, &sc->sc_mdhi);
552 err |= __put_user(regs->lo, &sc->sc_mdlo);
553 err |= __put_user(regs->cp0_cause, &sc->sc_cause);
554 err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr);
556 err |= __put_user(!!used_math(), &sc->sc_used_math);
558 if (!used_math())
559 goto out;
562 * Save FPU state to signal context. Signal handler will "inherit"
563 * current FPU state.
565 preempt_disable();
567 if (!is_fpu_owner()) {
568 own_fpu();
569 restore_fp(current);
571 err |= save_fp_context32(sc);
573 preempt_enable();
575 out:
576 return err;
580 * Determine which stack to use..
582 static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
583 size_t frame_size)
585 unsigned long sp;
587 /* Default to using normal stack */
588 sp = regs->regs[29];
591 * FPU emulator may have it's own trampoline active just
592 * above the user stack, 16-bytes before the next lowest
593 * 16 byte boundary. Try to avoid trashing it.
595 sp -= 32;
597 /* This is the X/Open sanctioned signal stack switching. */
598 if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
599 sp = current->sas_ss_sp + current->sas_ss_size;
601 return (void *)((sp - frame_size) & ALMASK);
604 static inline void setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
605 int signr, sigset_t *set)
607 struct sigframe *frame;
608 int err = 0;
610 frame = get_sigframe(ka, regs, sizeof(*frame));
611 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
612 goto give_sigsegv;
615 * Set up the return code ...
617 * li v0, __NR_O32_sigreturn
618 * syscall
620 err |= __put_user(0x24020000 + __NR_O32_sigreturn, frame->sf_code + 0);
621 err |= __put_user(0x0000000c , frame->sf_code + 1);
622 flush_cache_sigtramp((unsigned long) frame->sf_code);
624 err |= setup_sigcontext32(regs, &frame->sf_sc);
625 err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
626 if (err)
627 goto give_sigsegv;
630 * Arguments to signal handler:
632 * a0 = signal number
633 * a1 = 0 (should be cause)
634 * a2 = pointer to struct sigcontext
636 * $25 and c0_epc point to the signal handler, $29 points to the
637 * struct sigframe.
639 regs->regs[ 4] = signr;
640 regs->regs[ 5] = 0;
641 regs->regs[ 6] = (unsigned long) &frame->sf_sc;
642 regs->regs[29] = (unsigned long) frame;
643 regs->regs[31] = (unsigned long) frame->sf_code;
644 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
646 #if DEBUG_SIG
647 printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n",
648 current->comm, current->pid,
649 frame, regs->cp0_epc, frame->sf_code);
650 #endif
651 return;
653 give_sigsegv:
654 force_sigsegv(signr, current);
657 static inline void setup_rt_frame(struct k_sigaction * ka,
658 struct pt_regs *regs, int signr,
659 sigset_t *set, siginfo_t *info)
661 struct rt_sigframe32 *frame;
662 int err = 0;
663 s32 sp;
665 frame = get_sigframe(ka, regs, sizeof(*frame));
666 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
667 goto give_sigsegv;
669 /* Set up to return from userspace. If provided, use a stub already
670 in userspace. */
672 * Set up the return code ...
674 * li v0, __NR_O32_rt_sigreturn
675 * syscall
677 err |= __put_user(0x24020000 + __NR_O32_rt_sigreturn, frame->rs_code + 0);
678 err |= __put_user(0x0000000c , frame->rs_code + 1);
679 flush_cache_sigtramp((unsigned long) frame->rs_code);
681 /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
682 err |= copy_siginfo_to_user32(&frame->rs_info, info);
684 /* Create the ucontext. */
685 err |= __put_user(0, &frame->rs_uc.uc_flags);
686 err |= __put_user(0, &frame->rs_uc.uc_link);
687 sp = (int) (long) current->sas_ss_sp;
688 err |= __put_user(sp,
689 &frame->rs_uc.uc_stack.ss_sp);
690 err |= __put_user(sas_ss_flags(regs->regs[29]),
691 &frame->rs_uc.uc_stack.ss_flags);
692 err |= __put_user(current->sas_ss_size,
693 &frame->rs_uc.uc_stack.ss_size);
694 err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext);
695 err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
697 if (err)
698 goto give_sigsegv;
701 * Arguments to signal handler:
703 * a0 = signal number
704 * a1 = 0 (should be cause)
705 * a2 = pointer to ucontext
707 * $25 and c0_epc point to the signal handler, $29 points to
708 * the struct rt_sigframe32.
710 regs->regs[ 4] = signr;
711 regs->regs[ 5] = (unsigned long) &frame->rs_info;
712 regs->regs[ 6] = (unsigned long) &frame->rs_uc;
713 regs->regs[29] = (unsigned long) frame;
714 regs->regs[31] = (unsigned long) frame->rs_code;
715 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
717 #if DEBUG_SIG
718 printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n",
719 current->comm, current->pid,
720 frame, regs->cp0_epc, frame->rs_code);
721 #endif
722 return;
724 give_sigsegv:
725 force_sigsegv(signr, current);
728 static inline void handle_signal(unsigned long sig, siginfo_t *info,
729 struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs)
731 switch (regs->regs[0]) {
732 case ERESTART_RESTARTBLOCK:
733 case ERESTARTNOHAND:
734 regs->regs[2] = EINTR;
735 break;
736 case ERESTARTSYS:
737 if(!(ka->sa.sa_flags & SA_RESTART)) {
738 regs->regs[2] = EINTR;
739 break;
741 /* fallthrough */
742 case ERESTARTNOINTR: /* Userland will reload $v0. */
743 regs->regs[7] = regs->regs[26];
744 regs->cp0_epc -= 8;
747 regs->regs[0] = 0; /* Don't deal with this again. */
749 if (ka->sa.sa_flags & SA_SIGINFO)
750 setup_rt_frame(ka, regs, sig, oldset, info);
751 else
752 setup_frame(ka, regs, sig, oldset);
754 if (!(ka->sa.sa_flags & SA_NODEFER)) {
755 spin_lock_irq(&current->sighand->siglock);
756 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
757 sigaddset(&current->blocked,sig);
758 recalc_sigpending();
759 spin_unlock_irq(&current->sighand->siglock);
763 int do_signal32(sigset_t *oldset, struct pt_regs *regs)
765 struct k_sigaction ka;
766 siginfo_t info;
767 int signr;
770 * We want the common case to go fast, which is why we may in certain
771 * cases get here from kernel mode. Just return without doing anything
772 * if so.
774 if (!user_mode(regs))
775 return 1;
777 if (try_to_freeze(0))
778 goto no_signal;
780 if (!oldset)
781 oldset = &current->blocked;
783 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
784 if (signr > 0) {
785 handle_signal(signr, &info, &ka, oldset, regs);
786 return 1;
789 no_signal:
791 * Who's code doesn't conform to the restartable syscall convention
792 * dies here!!! The li instruction, a single machine instruction,
793 * must directly be followed by the syscall instruction.
795 if (regs->regs[0]) {
796 if (regs->regs[2] == ERESTARTNOHAND ||
797 regs->regs[2] == ERESTARTSYS ||
798 regs->regs[2] == ERESTARTNOINTR) {
799 regs->regs[7] = regs->regs[26];
800 regs->cp0_epc -= 8;
802 if (regs->regs[2] == ERESTART_RESTARTBLOCK) {
803 regs->regs[2] = __NR_O32_restart_syscall;
804 regs->regs[7] = regs->regs[26];
805 regs->cp0_epc -= 4;
808 return 0;
811 asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 *act,
812 struct sigaction32 *oact,
813 unsigned int sigsetsize)
815 struct k_sigaction new_sa, old_sa;
816 int ret = -EINVAL;
818 /* XXX: Don't preclude handling different sized sigset_t's. */
819 if (sigsetsize != sizeof(sigset_t))
820 goto out;
822 if (act) {
823 int err = 0;
825 if (!access_ok(VERIFY_READ, act, sizeof(*act)))
826 return -EFAULT;
827 err |= __get_user((u32)(u64)new_sa.sa.sa_handler,
828 &act->sa_handler);
829 err |= __get_user(new_sa.sa.sa_flags, &act->sa_flags);
830 err |= get_sigset(&new_sa.sa.sa_mask, &act->sa_mask);
831 if (err)
832 return -EFAULT;
835 ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
837 if (!ret && oact) {
838 int err = 0;
840 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
841 return -EFAULT;
843 err |= __put_user((u32)(u64)old_sa.sa.sa_handler,
844 &oact->sa_handler);
845 err |= __put_user(old_sa.sa.sa_flags, &oact->sa_flags);
846 err |= put_sigset(&old_sa.sa.sa_mask, &oact->sa_mask);
847 if (err)
848 return -EFAULT;
850 out:
851 return ret;
854 asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t *set,
855 compat_sigset_t *oset, unsigned int sigsetsize)
857 sigset_t old_set, new_set;
858 int ret;
859 mm_segment_t old_fs = get_fs();
861 if (set && get_sigset(&new_set, set))
862 return -EFAULT;
864 set_fs (KERNEL_DS);
865 ret = sys_rt_sigprocmask(how, set ? &new_set : NULL,
866 oset ? &old_set : NULL, sigsetsize);
867 set_fs (old_fs);
869 if (!ret && oset && put_sigset(&old_set, oset))
870 return -EFAULT;
872 return ret;
875 asmlinkage int sys32_rt_sigpending(compat_sigset_t *uset,
876 unsigned int sigsetsize)
878 int ret;
879 sigset_t set;
880 mm_segment_t old_fs = get_fs();
882 set_fs (KERNEL_DS);
883 ret = sys_rt_sigpending(&set, sigsetsize);
884 set_fs (old_fs);
886 if (!ret && put_sigset(&set, uset))
887 return -EFAULT;
889 return ret;
892 asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t *uinfo)
894 siginfo_t info;
895 int ret;
896 mm_segment_t old_fs = get_fs();
898 if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
899 copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
900 return -EFAULT;
901 set_fs (KERNEL_DS);
902 ret = sys_rt_sigqueueinfo(pid, sig, &info);
903 set_fs (old_fs);
904 return ret;