new helper: sigmask_to_save()
[linux-block.git] / arch / mips / kernel / signal32.c
CommitLineData
1da177e4
LT
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
dda73d0b 7 * Copyright (C) 1994 - 2000, 2006 Ralf Baechle
1da177e4
LT
8 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
9 */
02416dcf 10#include <linux/cache.h>
431dc804 11#include <linux/compat.h>
1da177e4
LT
12#include <linux/sched.h>
13#include <linux/mm.h>
14#include <linux/smp.h>
1da177e4
LT
15#include <linux/kernel.h>
16#include <linux/signal.h>
17#include <linux/syscalls.h>
18#include <linux/errno.h>
19#include <linux/wait.h>
20#include <linux/ptrace.h>
1da177e4
LT
21#include <linux/suspend.h>
22#include <linux/compiler.h>
faea6234 23#include <linux/uaccess.h>
1da177e4 24
e50c0a8f 25#include <asm/abi.h>
1da177e4 26#include <asm/asm.h>
431dc804 27#include <asm/compat-signal.h>
1da177e4
LT
28#include <linux/bitops.h>
29#include <asm/cacheflush.h>
30#include <asm/sim.h>
1da177e4 31#include <asm/ucontext.h>
1da177e4 32#include <asm/fpu.h>
02416dcf 33#include <asm/war.h>
d814c28c 34#include <asm/vdso.h>
b81947c6 35#include <asm/dsp.h>
1da177e4 36
36a1f2c2
FBH
37#include "signal-common.h"
38
137f6f3e
RB
39static int (*save_fp_context32)(struct sigcontext32 __user *sc);
40static int (*restore_fp_context32)(struct sigcontext32 __user *sc);
41
42extern asmlinkage int _save_fp_context32(struct sigcontext32 __user *sc);
43extern asmlinkage int _restore_fp_context32(struct sigcontext32 __user *sc);
44
45extern asmlinkage int fpu_emulator_save_context32(struct sigcontext32 __user *sc);
46extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 __user *sc);
47
1da177e4
LT
48/*
49 * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
50 */
151fd6ac 51#define __NR_O32_restart_syscall 4253
1da177e4 52
1da177e4
LT
53/* 32-bit compatibility types */
54
1da177e4
LT
55typedef unsigned int __sighandler32_t;
56typedef void (*vfptr_t)(void);
57
58struct sigaction32 {
59 unsigned int sa_flags;
60 __sighandler32_t sa_handler;
61 compat_sigset_t sa_mask;
62};
63
64/* IRIX compatible stack_t */
65typedef struct sigaltstack32 {
66 s32 ss_sp;
67 compat_size_t ss_size;
68 int ss_flags;
69} stack32_t;
70
71struct ucontext32 {
72 u32 uc_flags;
73 s32 uc_link;
74 stack32_t uc_stack;
75 struct sigcontext32 uc_mcontext;
01ee6037 76 compat_sigset_t uc_sigmask; /* mask last for extensibility */
1da177e4
LT
77};
78
dd02f06a
RB
79struct sigframe32 {
80 u32 sf_ass[4]; /* argument save space for o32 */
d814c28c 81 u32 sf_pad[2]; /* Was: signal trampoline */
dd02f06a 82 struct sigcontext32 sf_sc;
755f21bb 83 compat_sigset_t sf_mask;
dd02f06a
RB
84};
85
c0b9bae9
FBH
86struct rt_sigframe32 {
87 u32 rs_ass[4]; /* argument save space for o32 */
d814c28c 88 u32 rs_pad[2]; /* Was: signal trampoline */
c0b9bae9
FBH
89 compat_siginfo_t rs_info;
90 struct ucontext32 rs_uc;
91};
92
9432a9ba
FBH
93/*
94 * sigcontext handlers
95 */
faea6234
AN
96static int protected_save_fp_context32(struct sigcontext32 __user *sc)
97{
98 int err;
99 while (1) {
100 lock_fpu_owner();
101 own_fpu_inatomic(1);
102 err = save_fp_context32(sc); /* this might fail */
103 unlock_fpu_owner();
104 if (likely(!err))
105 break;
106 /* touch the sigcontext and try again */
107 err = __put_user(0, &sc->sc_fpregs[0]) |
108 __put_user(0, &sc->sc_fpregs[31]) |
109 __put_user(0, &sc->sc_fpc_csr);
110 if (err)
111 break; /* really bad sigcontext */
112 }
113 return err;
114}
115
116static int protected_restore_fp_context32(struct sigcontext32 __user *sc)
117{
c726b822 118 int err, tmp __maybe_unused;
faea6234
AN
119 while (1) {
120 lock_fpu_owner();
121 own_fpu_inatomic(0);
122 err = restore_fp_context32(sc); /* this might fail */
123 unlock_fpu_owner();
124 if (likely(!err))
125 break;
126 /* touch the sigcontext and try again */
127 err = __get_user(tmp, &sc->sc_fpregs[0]) |
128 __get_user(tmp, &sc->sc_fpregs[31]) |
129 __get_user(tmp, &sc->sc_fpc_csr);
130 if (err)
131 break; /* really bad sigcontext */
132 }
133 return err;
134}
135
9432a9ba
FBH
136static int setup_sigcontext32(struct pt_regs *regs,
137 struct sigcontext32 __user *sc)
138{
139 int err = 0;
140 int i;
53dc8028 141 u32 used_math;
9432a9ba
FBH
142
143 err |= __put_user(regs->cp0_epc, &sc->sc_pc);
9432a9ba
FBH
144
145 err |= __put_user(0, &sc->sc_regs[0]);
146 for (i = 1; i < 32; i++)
147 err |= __put_user(regs->regs[i], &sc->sc_regs[i]);
148
149 err |= __put_user(regs->hi, &sc->sc_mdhi);
150 err |= __put_user(regs->lo, &sc->sc_mdlo);
151 if (cpu_has_dsp) {
152 err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
153 err |= __put_user(mfhi1(), &sc->sc_hi1);
154 err |= __put_user(mflo1(), &sc->sc_lo1);
155 err |= __put_user(mfhi2(), &sc->sc_hi2);
156 err |= __put_user(mflo2(), &sc->sc_lo2);
157 err |= __put_user(mfhi3(), &sc->sc_hi3);
158 err |= __put_user(mflo3(), &sc->sc_lo3);
159 }
160
53dc8028
AN
161 used_math = !!used_math();
162 err |= __put_user(used_math, &sc->sc_used_math);
9432a9ba 163
53dc8028 164 if (used_math) {
9432a9ba
FBH
165 /*
166 * Save FPU state to signal context. Signal handler
167 * will "inherit" current FPU state.
168 */
faea6234 169 err |= protected_save_fp_context32(sc);
9432a9ba
FBH
170 }
171 return err;
172}
173
c6a2f467
AN
174static int
175check_and_restore_fp_context32(struct sigcontext32 __user *sc)
176{
177 int err, sig;
178
179 err = sig = fpcsr_pending(&sc->sc_fpc_csr);
180 if (err > 0)
181 err = 0;
faea6234 182 err |= protected_restore_fp_context32(sc);
c6a2f467
AN
183 return err ?: sig;
184}
185
9432a9ba
FBH
186static int restore_sigcontext32(struct pt_regs *regs,
187 struct sigcontext32 __user *sc)
188{
189 u32 used_math;
190 int err = 0;
191 s32 treg;
192 int i;
193
194 /* Always make any pending restarted system calls return -EINTR */
195 current_thread_info()->restart_block.fn = do_no_restart_syscall;
196
197 err |= __get_user(regs->cp0_epc, &sc->sc_pc);
198 err |= __get_user(regs->hi, &sc->sc_mdhi);
199 err |= __get_user(regs->lo, &sc->sc_mdlo);
200 if (cpu_has_dsp) {
201 err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
202 err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
203 err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
204 err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
205 err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
206 err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
207 err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
208 }
209
210 for (i = 1; i < 32; i++)
211 err |= __get_user(regs->regs[i], &sc->sc_regs[i]);
212
213 err |= __get_user(used_math, &sc->sc_used_math);
214 conditional_used_math(used_math);
215
53dc8028 216 if (used_math) {
9432a9ba 217 /* restore fpu context if we have used it before */
c6a2f467
AN
218 if (!err)
219 err = check_and_restore_fp_context32(sc);
9432a9ba
FBH
220 } else {
221 /* signal handler may have used FPU. Give it up. */
53dc8028 222 lose_fpu(0);
9432a9ba
FBH
223 }
224
9432a9ba
FBH
225 return err;
226}
227
228/*
229 *
230 */
1da177e4
LT
231extern void __put_sigset_unknown_nsig(void);
232extern void __get_sigset_unknown_nsig(void);
233
9bbf28a3 234static inline int put_sigset(const sigset_t *kbuf, compat_sigset_t __user *ubuf)
1da177e4
LT
235{
236 int err = 0;
237
238 if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)))
239 return -EFAULT;
240
241 switch (_NSIG_WORDS) {
242 default:
243 __put_sigset_unknown_nsig();
244 case 2:
49a89efb
RB
245 err |= __put_user(kbuf->sig[1] >> 32, &ubuf->sig[3]);
246 err |= __put_user(kbuf->sig[1] & 0xffffffff, &ubuf->sig[2]);
1da177e4 247 case 1:
49a89efb
RB
248 err |= __put_user(kbuf->sig[0] >> 32, &ubuf->sig[1]);
249 err |= __put_user(kbuf->sig[0] & 0xffffffff, &ubuf->sig[0]);
1da177e4
LT
250 }
251
252 return err;
253}
254
9c6031cc 255static inline int get_sigset(sigset_t *kbuf, const compat_sigset_t __user *ubuf)
1da177e4
LT
256{
257 int err = 0;
258 unsigned long sig[4];
259
260 if (!access_ok(VERIFY_READ, ubuf, sizeof(*ubuf)))
261 return -EFAULT;
262
263 switch (_NSIG_WORDS) {
264 default:
265 __get_sigset_unknown_nsig();
266 case 2:
49a89efb
RB
267 err |= __get_user(sig[3], &ubuf->sig[3]);
268 err |= __get_user(sig[2], &ubuf->sig[2]);
1da177e4
LT
269 kbuf->sig[1] = sig[2] | (sig[3] << 32);
270 case 1:
49a89efb
RB
271 err |= __get_user(sig[1], &ubuf->sig[1]);
272 err |= __get_user(sig[0], &ubuf->sig[0]);
1da177e4
LT
273 kbuf->sig[0] = sig[0] | (sig[1] << 32);
274 }
275
276 return err;
277}
278
279/*
280 * Atomically swap in the new signal mask, and wait for a signal.
281 */
282
f90080a0 283asmlinkage int sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
1da177e4 284{
9c6031cc 285 compat_sigset_t __user *uset;
68fa383f 286 sigset_t newset;
1da177e4 287
9c6031cc 288 uset = (compat_sigset_t __user *) regs.regs[4];
1da177e4
LT
289 if (get_sigset(&newset, uset))
290 return -EFAULT;
68f3f16d 291 return sigsuspend(&newset);
1da177e4
LT
292}
293
f90080a0 294asmlinkage int sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
1da177e4 295{
9c6031cc 296 compat_sigset_t __user *uset;
68fa383f 297 sigset_t newset;
304416da 298 size_t sigsetsize;
1da177e4
LT
299
300 /* XXX Don't preclude handling different sized sigset_t's. */
301 sigsetsize = regs.regs[5];
302 if (sigsetsize != sizeof(compat_sigset_t))
303 return -EINVAL;
304
9c6031cc 305 uset = (compat_sigset_t __user *) regs.regs[4];
1da177e4
LT
306 if (get_sigset(&newset, uset))
307 return -EFAULT;
68f3f16d 308 return sigsuspend(&newset);
1da177e4
LT
309}
310
dbda6ac0
RB
311SYSCALL_DEFINE3(32_sigaction, long, sig, const struct sigaction32 __user *, act,
312 struct sigaction32 __user *, oact)
1da177e4
LT
313{
314 struct k_sigaction new_ka, old_ka;
315 int ret;
316 int err = 0;
317
318 if (act) {
319 old_sigset_t mask;
77c728c2 320 s32 handler;
1da177e4
LT
321
322 if (!access_ok(VERIFY_READ, act, sizeof(*act)))
323 return -EFAULT;
77c728c2 324 err |= __get_user(handler, &act->sa_handler);
9bbf28a3 325 new_ka.sa.sa_handler = (void __user *)(s64)handler;
1da177e4
LT
326 err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
327 err |= __get_user(mask, &act->sa_mask.sig[0]);
328 if (err)
329 return -EFAULT;
330
331 siginitset(&new_ka.sa.sa_mask, mask);
332 }
333
334 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
335
336 if (!ret && oact) {
337 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
6254944f 338 return -EFAULT;
1da177e4
LT
339 err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
340 err |= __put_user((u32)(u64)old_ka.sa.sa_handler,
341 &oact->sa_handler);
342 err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
6254944f
MM
343 err |= __put_user(0, &oact->sa_mask.sig[1]);
344 err |= __put_user(0, &oact->sa_mask.sig[2]);
345 err |= __put_user(0, &oact->sa_mask.sig[3]);
346 if (err)
1da177e4
LT
347 return -EFAULT;
348 }
349
350 return ret;
351}
352
353asmlinkage int sys32_sigaltstack(nabi_no_regargs struct pt_regs regs)
354{
9bbf28a3
AN
355 const stack32_t __user *uss = (const stack32_t __user *) regs.regs[4];
356 stack32_t __user *uoss = (stack32_t __user *) regs.regs[5];
1da177e4
LT
357 unsigned long usp = regs.regs[29];
358 stack_t kss, koss;
359 int ret, err = 0;
360 mm_segment_t old_fs = get_fs();
361 s32 sp;
362
363 if (uss) {
364 if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
365 return -EFAULT;
366 err |= __get_user(sp, &uss->ss_sp);
9c6031cc 367 kss.ss_sp = (void __user *) (long) sp;
1da177e4
LT
368 err |= __get_user(kss.ss_size, &uss->ss_size);
369 err |= __get_user(kss.ss_flags, &uss->ss_flags);
370 if (err)
371 return -EFAULT;
372 }
373
49a89efb 374 set_fs(KERNEL_DS);
9bbf28a3
AN
375 ret = do_sigaltstack(uss ? (stack_t __user *)&kss : NULL,
376 uoss ? (stack_t __user *)&koss : NULL, usp);
49a89efb 377 set_fs(old_fs);
1da177e4
LT
378
379 if (!ret && uoss) {
380 if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
381 return -EFAULT;
9c6031cc 382 sp = (int) (unsigned long) koss.ss_sp;
1da177e4
LT
383 err |= __put_user(sp, &uoss->ss_sp);
384 err |= __put_user(koss.ss_size, &uoss->ss_size);
385 err |= __put_user(koss.ss_flags, &uoss->ss_flags);
386 if (err)
387 return -EFAULT;
388 }
389 return ret;
390}
391
9bbf28a3 392int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
1da177e4
LT
393{
394 int err;
395
396 if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
397 return -EFAULT;
398
399 /* If you change siginfo_t structure, please be sure
400 this code is fixed accordingly.
401 It should never copy any pad contained in the structure
402 to avoid security leaks, but must copy the generic
403 3 ints plus the relevant union member.
404 This routine must convert siginfo from 64bit to 32bit as well
405 at the same time. */
406 err = __put_user(from->si_signo, &to->si_signo);
407 err |= __put_user(from->si_errno, &to->si_errno);
408 err |= __put_user((short)from->si_code, &to->si_code);
409 if (from->si_code < 0)
410 err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
411 else {
412 switch (from->si_code >> 16) {
a982099c
RB
413 case __SI_TIMER >> 16:
414 err |= __put_user(from->si_tid, &to->si_tid);
415 err |= __put_user(from->si_overrun, &to->si_overrun);
416 err |= __put_user(from->si_int, &to->si_int);
417 break;
1da177e4
LT
418 case __SI_CHLD >> 16:
419 err |= __put_user(from->si_utime, &to->si_utime);
420 err |= __put_user(from->si_stime, &to->si_stime);
421 err |= __put_user(from->si_status, &to->si_status);
422 default:
423 err |= __put_user(from->si_pid, &to->si_pid);
424 err |= __put_user(from->si_uid, &to->si_uid);
425 break;
426 case __SI_FAULT >> 16:
5665a0ac 427 err |= __put_user((unsigned long)from->si_addr, &to->si_addr);
1da177e4
LT
428 break;
429 case __SI_POLL >> 16:
430 err |= __put_user(from->si_band, &to->si_band);
431 err |= __put_user(from->si_fd, &to->si_fd);
432 break;
433 case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
434 case __SI_MESGQ >> 16:
435 err |= __put_user(from->si_pid, &to->si_pid);
436 err |= __put_user(from->si_uid, &to->si_uid);
437 err |= __put_user(from->si_int, &to->si_int);
438 break;
439 }
440 }
441 return err;
442}
443
5d9a76cd
TB
444int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
445{
446 memset(to, 0, sizeof *to);
447
448 if (copy_from_user(to, from, 3*sizeof(int)) ||
449 copy_from_user(to->_sifields._pad,
450 from->_sifields._pad, SI_PAD_SIZE32))
451 return -EFAULT;
452
453 return 0;
454}
455
f90080a0 456asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
1da177e4 457{
dd02f06a 458 struct sigframe32 __user *frame;
1da177e4 459 sigset_t blocked;
c6a2f467 460 int sig;
1da177e4 461
dd02f06a 462 frame = (struct sigframe32 __user *) regs.regs[29];
1da177e4
LT
463 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
464 goto badframe;
431dc804 465 if (__copy_conv_sigset_from_user(&blocked, &frame->sf_mask))
1da177e4
LT
466 goto badframe;
467
468 sigdelsetmask(&blocked, ~_BLOCKABLE);
8598f3cd 469 set_current_blocked(&blocked);
1da177e4 470
c6a2f467
AN
471 sig = restore_sigcontext32(&regs, &frame->sf_sc);
472 if (sig < 0)
1da177e4 473 goto badframe;
c6a2f467
AN
474 else if (sig)
475 force_sig(sig, current);
1da177e4
LT
476
477 /*
478 * Don't let your children do this ...
479 */
1da177e4
LT
480 __asm__ __volatile__(
481 "move\t$29, %0\n\t"
482 "j\tsyscall_exit"
483 :/* no outputs */
484 :"r" (&regs));
485 /* Unreached */
486
487badframe:
488 force_sig(SIGSEGV, current);
489}
490
f90080a0 491asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
1da177e4 492{
9bbf28a3 493 struct rt_sigframe32 __user *frame;
1fcf1cc7 494 mm_segment_t old_fs;
1da177e4
LT
495 sigset_t set;
496 stack_t st;
497 s32 sp;
c6a2f467 498 int sig;
1da177e4 499
9bbf28a3 500 frame = (struct rt_sigframe32 __user *) regs.regs[29];
1da177e4
LT
501 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
502 goto badframe;
431dc804 503 if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask))
1da177e4
LT
504 goto badframe;
505
506 sigdelsetmask(&set, ~_BLOCKABLE);
8598f3cd 507 set_current_blocked(&set);
1da177e4 508
c6a2f467
AN
509 sig = restore_sigcontext32(&regs, &frame->rs_uc.uc_mcontext);
510 if (sig < 0)
1da177e4 511 goto badframe;
c6a2f467
AN
512 else if (sig)
513 force_sig(sig, current);
1da177e4
LT
514
515 /* The ucontext contains a stack32_t, so we must convert! */
516 if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp))
517 goto badframe;
9c6031cc 518 st.ss_sp = (void __user *)(long) sp;
1da177e4
LT
519 if (__get_user(st.ss_size, &frame->rs_uc.uc_stack.ss_size))
520 goto badframe;
521 if (__get_user(st.ss_flags, &frame->rs_uc.uc_stack.ss_flags))
522 goto badframe;
523
524 /* It is more difficult to avoid calling this function than to
525 call it and ignore errors. */
1fcf1cc7 526 old_fs = get_fs();
49a89efb 527 set_fs(KERNEL_DS);
9bbf28a3 528 do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]);
49a89efb 529 set_fs(old_fs);
1da177e4
LT
530
531 /*
532 * Don't let your children do this ...
533 */
534 __asm__ __volatile__(
535 "move\t$29, %0\n\t"
536 "j\tsyscall_exit"
537 :/* no outputs */
538 :"r" (&regs));
539 /* Unreached */
540
541badframe:
542 force_sig(SIGSEGV, current);
543}
544
d814c28c
DD
545static int setup_frame_32(void *sig_return, struct k_sigaction *ka,
546 struct pt_regs *regs, int signr, sigset_t *set)
1da177e4 547{
dd02f06a 548 struct sigframe32 __user *frame;
1da177e4
LT
549 int err = 0;
550
551 frame = get_sigframe(ka, regs, sizeof(*frame));
552 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
553 goto give_sigsegv;
554
1da177e4 555 err |= setup_sigcontext32(regs, &frame->sf_sc);
431dc804
RB
556 err |= __copy_conv_sigset_to_user(&frame->sf_mask, set);
557
1da177e4
LT
558 if (err)
559 goto give_sigsegv;
560
561 /*
562 * Arguments to signal handler:
563 *
564 * a0 = signal number
565 * a1 = 0 (should be cause)
566 * a2 = pointer to struct sigcontext
567 *
568 * $25 and c0_epc point to the signal handler, $29 points to the
569 * struct sigframe.
570 */
571 regs->regs[ 4] = signr;
572 regs->regs[ 5] = 0;
573 regs->regs[ 6] = (unsigned long) &frame->sf_sc;
574 regs->regs[29] = (unsigned long) frame;
d814c28c 575 regs->regs[31] = (unsigned long) sig_return;
1da177e4
LT
576 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
577
722bb63d 578 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
1da177e4 579 current->comm, current->pid,
722bb63d
FBH
580 frame, regs->cp0_epc, regs->regs[31]);
581
7b3e2fc8 582 return 0;
1da177e4
LT
583
584give_sigsegv:
585 force_sigsegv(signr, current);
7b3e2fc8 586 return -EFAULT;
1da177e4
LT
587}
588
d814c28c
DD
589static int setup_rt_frame_32(void *sig_return, struct k_sigaction *ka,
590 struct pt_regs *regs, int signr, sigset_t *set,
591 siginfo_t *info)
1da177e4 592{
9bbf28a3 593 struct rt_sigframe32 __user *frame;
1da177e4
LT
594 int err = 0;
595 s32 sp;
596
597 frame = get_sigframe(ka, regs, sizeof(*frame));
598 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
599 goto give_sigsegv;
600
1da177e4
LT
601 /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
602 err |= copy_siginfo_to_user32(&frame->rs_info, info);
603
604 /* Create the ucontext. */
605 err |= __put_user(0, &frame->rs_uc.uc_flags);
606 err |= __put_user(0, &frame->rs_uc.uc_link);
607 sp = (int) (long) current->sas_ss_sp;
608 err |= __put_user(sp,
609 &frame->rs_uc.uc_stack.ss_sp);
610 err |= __put_user(sas_ss_flags(regs->regs[29]),
611 &frame->rs_uc.uc_stack.ss_flags);
612 err |= __put_user(current->sas_ss_size,
613 &frame->rs_uc.uc_stack.ss_size);
614 err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext);
431dc804 615 err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
1da177e4
LT
616
617 if (err)
618 goto give_sigsegv;
619
620 /*
621 * Arguments to signal handler:
622 *
623 * a0 = signal number
624 * a1 = 0 (should be cause)
625 * a2 = pointer to ucontext
626 *
627 * $25 and c0_epc point to the signal handler, $29 points to
628 * the struct rt_sigframe32.
629 */
630 regs->regs[ 4] = signr;
631 regs->regs[ 5] = (unsigned long) &frame->rs_info;
632 regs->regs[ 6] = (unsigned long) &frame->rs_uc;
633 regs->regs[29] = (unsigned long) frame;
d814c28c 634 regs->regs[31] = (unsigned long) sig_return;
1da177e4
LT
635 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
636
722bb63d 637 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
1da177e4 638 current->comm, current->pid,
722bb63d
FBH
639 frame, regs->cp0_epc, regs->regs[31]);
640
7b3e2fc8 641 return 0;
1da177e4
LT
642
643give_sigsegv:
644 force_sigsegv(signr, current);
7b3e2fc8 645 return -EFAULT;
1da177e4
LT
646}
647
151fd6ac
RB
648/*
649 * o32 compatibility on 64-bit kernels, without DSP ASE
650 */
651struct mips_abi mips_abi_32 = {
652 .setup_frame = setup_frame_32,
d814c28c
DD
653 .signal_return_offset =
654 offsetof(struct mips_vdso, o32_signal_trampoline),
151fd6ac 655 .setup_rt_frame = setup_rt_frame_32,
d814c28c
DD
656 .rt_signal_return_offset =
657 offsetof(struct mips_vdso, o32_rt_signal_trampoline),
151fd6ac
RB
658 .restart = __NR_O32_restart_syscall
659};
1da177e4 660
dbda6ac0
RB
661SYSCALL_DEFINE4(32_rt_sigaction, int, sig,
662 const struct sigaction32 __user *, act,
663 struct sigaction32 __user *, oact, unsigned int, sigsetsize)
1da177e4
LT
664{
665 struct k_sigaction new_sa, old_sa;
666 int ret = -EINVAL;
667
668 /* XXX: Don't preclude handling different sized sigset_t's. */
669 if (sigsetsize != sizeof(sigset_t))
670 goto out;
671
672 if (act) {
77c728c2 673 s32 handler;
1da177e4
LT
674 int err = 0;
675
676 if (!access_ok(VERIFY_READ, act, sizeof(*act)))
677 return -EFAULT;
77c728c2 678 err |= __get_user(handler, &act->sa_handler);
9bbf28a3 679 new_sa.sa.sa_handler = (void __user *)(s64)handler;
1da177e4
LT
680 err |= __get_user(new_sa.sa.sa_flags, &act->sa_flags);
681 err |= get_sigset(&new_sa.sa.sa_mask, &act->sa_mask);
682 if (err)
683 return -EFAULT;
684 }
685
686 ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
687
688 if (!ret && oact) {
689 int err = 0;
690
691 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
692 return -EFAULT;
693
694 err |= __put_user((u32)(u64)old_sa.sa.sa_handler,
695 &oact->sa_handler);
696 err |= __put_user(old_sa.sa.sa_flags, &oact->sa_flags);
697 err |= put_sigset(&old_sa.sa.sa_mask, &oact->sa_mask);
698 if (err)
699 return -EFAULT;
700 }
701out:
702 return ret;
703}
704
dbda6ac0
RB
705SYSCALL_DEFINE4(32_rt_sigprocmask, int, how, compat_sigset_t __user *, set,
706 compat_sigset_t __user *, oset, unsigned int, sigsetsize)
1da177e4
LT
707{
708 sigset_t old_set, new_set;
709 int ret;
710 mm_segment_t old_fs = get_fs();
711
712 if (set && get_sigset(&new_set, set))
713 return -EFAULT;
714
49a89efb 715 set_fs(KERNEL_DS);
9bbf28a3
AN
716 ret = sys_rt_sigprocmask(how, set ? (sigset_t __user *)&new_set : NULL,
717 oset ? (sigset_t __user *)&old_set : NULL,
718 sigsetsize);
49a89efb 719 set_fs(old_fs);
1da177e4
LT
720
721 if (!ret && oset && put_sigset(&old_set, oset))
722 return -EFAULT;
723
724 return ret;
725}
726
dbda6ac0
RB
727SYSCALL_DEFINE2(32_rt_sigpending, compat_sigset_t __user *, uset,
728 unsigned int, sigsetsize)
1da177e4
LT
729{
730 int ret;
731 sigset_t set;
732 mm_segment_t old_fs = get_fs();
733
49a89efb 734 set_fs(KERNEL_DS);
9bbf28a3 735 ret = sys_rt_sigpending((sigset_t __user *)&set, sigsetsize);
49a89efb 736 set_fs(old_fs);
1da177e4
LT
737
738 if (!ret && put_sigset(&set, uset))
739 return -EFAULT;
740
741 return ret;
742}
743
dbda6ac0
RB
744SYSCALL_DEFINE3(32_rt_sigqueueinfo, int, pid, int, sig,
745 compat_siginfo_t __user *, uinfo)
1da177e4
LT
746{
747 siginfo_t info;
748 int ret;
749 mm_segment_t old_fs = get_fs();
750
49a89efb
RB
751 if (copy_from_user(&info, uinfo, 3*sizeof(int)) ||
752 copy_from_user(info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
1da177e4 753 return -EFAULT;
49a89efb 754 set_fs(KERNEL_DS);
9bbf28a3 755 ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *)&info);
49a89efb 756 set_fs(old_fs);
1da177e4
LT
757 return ret;
758}
54f2da75 759
dbda6ac0
RB
760SYSCALL_DEFINE5(32_waitid, int, which, compat_pid_t, pid,
761 compat_siginfo_t __user *, uinfo, int, options,
762 struct compat_rusage __user *, uru)
54f2da75
RB
763{
764 siginfo_t info;
765 struct rusage ru;
766 long ret;
767 mm_segment_t old_fs = get_fs();
768
769 info.si_signo = 0;
49a89efb 770 set_fs(KERNEL_DS);
54f2da75
RB
771 ret = sys_waitid(which, pid, (siginfo_t __user *) &info, options,
772 uru ? (struct rusage __user *) &ru : NULL);
49a89efb 773 set_fs(old_fs);
54f2da75
RB
774
775 if (ret < 0 || info.si_signo == 0)
776 return ret;
777
778 if (uru && (ret = put_compat_rusage(&ru, uru)))
779 return ret;
780
781 BUG_ON(info.si_code & __SI_MASK);
782 info.si_code |= __SI_CHLD;
783 return copy_siginfo_to_user32(uinfo, &info);
784}
137f6f3e
RB
785
786static int signal32_init(void)
787{
788 if (cpu_has_fpu) {
789 save_fp_context32 = _save_fp_context32;
790 restore_fp_context32 = _restore_fp_context32;
791 } else {
792 save_fp_context32 = fpu_emulator_save_context32;
793 restore_fp_context32 = fpu_emulator_restore_context32;
794 }
795
796 return 0;
797}
798
799arch_initcall(signal32_init);