aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/signal32.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/signal32.c')
-rw-r--r--arch/mips/kernel/signal32.c905
1 files changed, 905 insertions, 0 deletions
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
new file mode 100644
index 000000000000..1f3b19124c01
--- /dev/null
+++ b/arch/mips/kernel/signal32.c
@@ -0,0 +1,905 @@
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.
5 *
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>
23
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>
32
33#define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3)
34
35typedef struct compat_siginfo {
36 int si_signo;
37 int si_code;
38 int si_errno;
39
40 union {
41 int _pad[SI_PAD_SIZE32];
42
43 /* kill() */
44 struct {
45 compat_pid_t _pid; /* sender's pid */
46 compat_uid_t _uid; /* sender's uid */
47 } _kill;
48
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;
57
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;
65
66 /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
67 struct {
68 s32 _addr; /* faulting insn/memory ref. */
69 } _sigfault;
70
71 /* SIGPOLL, SIGXFSZ (To do ...) */
72 struct {
73 int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
74 int _fd;
75 } _sigpoll;
76
77 /* POSIX.1b timers */
78 struct {
79 unsigned int _timer1;
80 unsigned int _timer2;
81 } _timer;
82
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;
89
90 } _sifields;
91} compat_siginfo_t;
92
93/*
94 * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
95 */
96#define __NR_O32_sigreturn 4119
97#define __NR_O32_rt_sigreturn 4193
98#define __NR_O32_restart_syscall 4253
99
100#define DEBUG_SIG 0
101
102#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
103
104extern int do_signal32(sigset_t *oldset, struct pt_regs *regs);
105
106/* 32-bit compatibility types */
107
108#define _NSIG_BPW32 32
109#define _NSIG_WORDS32 (_NSIG / _NSIG_BPW32)
110
111typedef struct {
112 unsigned int sig[_NSIG_WORDS32];
113} sigset_t32;
114
115typedef unsigned int __sighandler32_t;
116typedef void (*vfptr_t)(void);
117
118struct sigaction32 {
119 unsigned int sa_flags;
120 __sighandler32_t sa_handler;
121 compat_sigset_t sa_mask;
122};
123
124/* IRIX compatible stack_t */
125typedef struct sigaltstack32 {
126 s32 ss_sp;
127 compat_size_t ss_size;
128 int ss_flags;
129} stack32_t;
130
131struct 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 */
137};
138
139extern void __put_sigset_unknown_nsig(void);
140extern void __get_sigset_unknown_nsig(void);
141
142static inline int put_sigset(const sigset_t *kbuf, compat_sigset_t *ubuf)
143{
144 int err = 0;
145
146 if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)))
147 return -EFAULT;
148
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]);
158 }
159
160 return err;
161}
162
163static inline int get_sigset(sigset_t *kbuf, const compat_sigset_t *ubuf)
164{
165 int err = 0;
166 unsigned long sig[4];
167
168 if (!access_ok(VERIFY_READ, ubuf, sizeof(*ubuf)))
169 return -EFAULT;
170
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);
182 }
183
184 return err;
185}
186
187/*
188 * Atomically swap in the new signal mask, and wait for a signal.
189 */
190
191save_static_function(sys32_sigsuspend);
192__attribute_used__ noinline static int
193_sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
194{
195 compat_sigset_t *uset;
196 sigset_t newset, saveset;
197
198 uset = (compat_sigset_t *) regs.regs[4];
199 if (get_sigset(&newset, uset))
200 return -EFAULT;
201 sigdelsetmask(&newset, ~_BLOCKABLE);
202
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);
208
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;
216 }
217}
218
219save_static_function(sys32_rt_sigsuspend);
220__attribute_used__ noinline static int
221_sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
222{
223 compat_sigset_t *uset;
224 sigset_t newset, saveset;
225 size_t sigsetsize;
226
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;
231
232 uset = (compat_sigset_t *) regs.regs[4];
233 if (get_sigset(&newset, uset))
234 return -EFAULT;
235 sigdelsetmask(&newset, ~_BLOCKABLE);
236
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);
242
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;
250 }
251}
252
253asmlinkage int sys32_sigaction(int sig, const struct sigaction32 *act,
254 struct sigaction32 *oact)
255{
256 struct k_sigaction new_ka, old_ka;
257 int ret;
258 int err = 0;
259
260 if (act) {
261 old_sigset_t mask;
262
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;
271
272 siginitset(&new_ka.sa.sa_mask, mask);
273 }
274
275 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
276
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;
289 }
290
291 return ret;
292}
293
294asmlinkage int sys32_sigaltstack(nabi_no_regargs struct pt_regs regs)
295{
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;
303
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;
313 }
314
315 set_fs (KERNEL_DS);
316 ret = do_sigaltstack(uss ? &kss : NULL , uoss ? &koss : NULL, usp);
317 set_fs (old_fs);
318
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;
328 }
329 return ret;
330}
331
332static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 *sc)
333{
334 int err = 0;
335 __u32 used_math;
336
337 /* Always make any pending restarted system calls return -EINTR */
338 current_thread_info()->restart_block.fn = do_no_restart_syscall;
339
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);
343
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
359
360 err |= __get_user(used_math, &sc->sc_used_math);
361 conditional_used_math(used_math);
362
363 preempt_disable();
364
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();
372 }
373
374 preempt_enable();
375
376 return err;
377}
378
379struct 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;
384};
385
386struct 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;
391};
392
393int copy_siginfo_to_user32(compat_siginfo_t *to, siginfo_t *from)
394{
395 int err;
396
397 if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
398 return -EFAULT;
399
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;
435 }
436 }
437 return err;
438}
439
440save_static_function(sys32_sigreturn);
441__attribute_used__ noinline static void
442_sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
443{
444 struct sigframe *frame;
445 sigset_t blocked;
446
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;
452
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);
458
459 if (restore_sigcontext32(&regs, &frame->sf_sc))
460 goto badframe;
461
462 /*
463 * Don't let your children do this ...
464 */
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 */
473
474badframe:
475 force_sig(SIGSEGV, current);
476}
477
478save_static_function(sys32_rt_sigreturn);
479__attribute_used__ noinline static void
480_sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
481{
482 struct rt_sigframe32 *frame;
483 sigset_t set;
484 stack_t st;
485 s32 sp;
486
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;
492
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);
498
499 if (restore_sigcontext32(&regs, &frame->rs_uc.uc_mcontext))
500 goto badframe;
501
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;
510
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]);
514
515 /*
516 * Don't let your children do this ...
517 */
518 __asm__ __volatile__(
519 "move\t$29, %0\n\t"
520 "j\tsyscall_exit"
521 :/* no outputs */
522 :"r" (&regs));
523 /* Unreached */
524
525badframe:
526 force_sig(SIGSEGV, current);
527}
528
529static inline int setup_sigcontext32(struct pt_regs *regs,
530 struct sigcontext32 *sc)
531{
532 int err = 0;
533
534 err |= __put_user(regs->cp0_epc, &sc->sc_pc);
535 err |= __put_user(regs->cp0_status, &sc->sc_status);
536
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
550
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);
555
556 err |= __put_user(!!used_math(), &sc->sc_used_math);
557
558 if (!used_math())
559 goto out;
560
561 /*
562 * Save FPU state to signal context. Signal handler will "inherit"
563 * current FPU state.
564 */
565 preempt_disable();
566
567 if (!is_fpu_owner()) {
568 own_fpu();
569 restore_fp(current);
570 }
571 err |= save_fp_context32(sc);
572
573 preempt_enable();
574
575out:
576 return err;
577}
578
579/*
580 * Determine which stack to use..
581 */
582static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
583 size_t frame_size)
584{
585 unsigned long sp;
586
587 /* Default to using normal stack */
588 sp = regs->regs[29];
589
590 /*
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.
594 */
595 sp -= 32;
596
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;
600
601 return (void *)((sp - frame_size) & ALMASK);
602}
603
604static inline void setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
605 int signr, sigset_t *set)
606{
607 struct sigframe *frame;
608 int err = 0;
609
610 frame = get_sigframe(ka, regs, sizeof(*frame));
611 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
612 goto give_sigsegv;
613
614 /*
615 * Set up the return code ...
616 *
617 * li v0, __NR_O32_sigreturn
618 * syscall
619 */
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);
623
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;
628
629 /*
630 * Arguments to signal handler:
631 *
632 * a0 = signal number
633 * a1 = 0 (should be cause)
634 * a2 = pointer to struct sigcontext
635 *
636 * $25 and c0_epc point to the signal handler, $29 points to the
637 * struct sigframe.
638 */
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;
645
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;
652
653give_sigsegv:
654 force_sigsegv(signr, current);
655}
656
657static inline void setup_rt_frame(struct k_sigaction * ka,
658 struct pt_regs *regs, int signr,
659 sigset_t *set, siginfo_t *info)
660{
661 struct rt_sigframe32 *frame;
662 int err = 0;
663 s32 sp;
664
665 frame = get_sigframe(ka, regs, sizeof(*frame));
666 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
667 goto give_sigsegv;
668
669 /* Set up to return from userspace. If provided, use a stub already
670 in userspace. */
671 /*
672 * Set up the return code ...
673 *
674 * li v0, __NR_O32_rt_sigreturn
675 * syscall
676 */
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);
680
681 /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
682 err |= copy_siginfo_to_user32(&frame->rs_info, info);
683
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));
696
697 if (err)
698 goto give_sigsegv;
699
700 /*
701 * Arguments to signal handler:
702 *
703 * a0 = signal number
704 * a1 = 0 (should be cause)
705 * a2 = pointer to ucontext
706 *
707 * $25 and c0_epc point to the signal handler, $29 points to
708 * the struct rt_sigframe32.
709 */
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;
716
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;
723
724give_sigsegv:
725 force_sigsegv(signr, current);
726}
727
728static inline void handle_signal(unsigned long sig, siginfo_t *info,
729 struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs)
730{
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;
740 }
741 /* fallthrough */
742 case ERESTARTNOINTR: /* Userland will reload $v0. */
743 regs->regs[7] = regs->regs[26];
744 regs->cp0_epc -= 8;
745 }
746
747 regs->regs[0] = 0; /* Don't deal with this again. */
748
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);
753
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);
760 }
761}
762
763int do_signal32(sigset_t *oldset, struct pt_regs *regs)
764{
765 struct k_sigaction ka;
766 siginfo_t info;
767 int signr;
768
769 /*
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.
773 */
774 if (!user_mode(regs))
775 return 1;
776
777 if (try_to_freeze(0))
778 goto no_signal;
779
780 if (!oldset)
781 oldset = &current->blocked;
782
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;
787 }
788
789no_signal:
790 /*
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.
794 */
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;
801 }
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;
806 }
807 }
808 return 0;
809}
810
811asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 *act,
812 struct sigaction32 *oact,
813 unsigned int sigsetsize)
814{
815 struct k_sigaction new_sa, old_sa;
816 int ret = -EINVAL;
817
818 /* XXX: Don't preclude handling different sized sigset_t's. */
819 if (sigsetsize != sizeof(sigset_t))
820 goto out;
821
822 if (act) {
823 int err = 0;
824
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;
833 }
834
835 ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
836
837 if (!ret && oact) {
838 int err = 0;
839
840 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
841 return -EFAULT;
842
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;
849 }
850out:
851 return ret;
852}
853
854asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t *set,
855 compat_sigset_t *oset, unsigned int sigsetsize)
856{
857 sigset_t old_set, new_set;
858 int ret;
859 mm_segment_t old_fs = get_fs();
860
861 if (set && get_sigset(&new_set, set))
862 return -EFAULT;
863
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);
868
869 if (!ret && oset && put_sigset(&old_set, oset))
870 return -EFAULT;
871
872 return ret;
873}
874
875asmlinkage int sys32_rt_sigpending(compat_sigset_t *uset,
876 unsigned int sigsetsize)
877{
878 int ret;
879 sigset_t set;
880 mm_segment_t old_fs = get_fs();
881
882 set_fs (KERNEL_DS);
883 ret = sys_rt_sigpending(&set, sigsetsize);
884 set_fs (old_fs);
885
886 if (!ret && put_sigset(&set, uset))
887 return -EFAULT;
888
889 return ret;
890}
891
892asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t *uinfo)
893{
894 siginfo_t info;
895 int ret;
896 mm_segment_t old_fs = get_fs();
897
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;
905}