blob: 136260c8f756a69f3adfcd91f6b211dd2ad75673 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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 */
Ralf Baechle02416dc2005-06-15 13:00:12 +000010#include <linux/cache.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070011#include <linux/sched.h>
12#include <linux/mm.h>
13#include <linux/smp.h>
14#include <linux/smp_lock.h>
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>
21#include <linux/compat.h>
22#include <linux/suspend.h>
23#include <linux/compiler.h>
24
Ralf Baechlee50c0a82005-05-31 11:49:19 +000025#include <asm/abi.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <asm/asm.h>
27#include <linux/bitops.h>
28#include <asm/cacheflush.h>
29#include <asm/sim.h>
30#include <asm/uaccess.h>
31#include <asm/ucontext.h>
32#include <asm/system.h>
33#include <asm/fpu.h>
Ralf Baechle02416dc2005-06-15 13:00:12 +000034#include <asm/war.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
36#define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3)
37
38typedef struct compat_siginfo {
39 int si_signo;
40 int si_code;
41 int si_errno;
42
43 union {
44 int _pad[SI_PAD_SIZE32];
45
46 /* kill() */
47 struct {
48 compat_pid_t _pid; /* sender's pid */
49 compat_uid_t _uid; /* sender's uid */
50 } _kill;
51
52 /* SIGCHLD */
53 struct {
54 compat_pid_t _pid; /* which child */
55 compat_uid_t _uid; /* sender's uid */
56 int _status; /* exit code */
57 compat_clock_t _utime;
58 compat_clock_t _stime;
59 } _sigchld;
60
61 /* IRIX SIGCHLD */
62 struct {
63 compat_pid_t _pid; /* which child */
64 compat_clock_t _utime;
65 int _status; /* exit code */
66 compat_clock_t _stime;
67 } _irix_sigchld;
68
69 /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
70 struct {
71 s32 _addr; /* faulting insn/memory ref. */
72 } _sigfault;
73
74 /* SIGPOLL, SIGXFSZ (To do ...) */
75 struct {
76 int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
77 int _fd;
78 } _sigpoll;
79
80 /* POSIX.1b timers */
81 struct {
Ralf Baechlea9820992005-02-16 21:24:16 +000082 timer_t _tid; /* timer id */
83 int _overrun; /* overrun count */
Ralf Baechle209ac8d2005-03-18 17:36:42 +000084 compat_sigval_t _sigval;/* same as below */
Ralf Baechlea9820992005-02-16 21:24:16 +000085 int _sys_private; /* not to be passed to user */
Linus Torvalds1da177e2005-04-16 15:20:36 -070086 } _timer;
87
88 /* POSIX.1b signals */
89 struct {
90 compat_pid_t _pid; /* sender's pid */
91 compat_uid_t _uid; /* sender's uid */
92 compat_sigval_t _sigval;
93 } _rt;
94
95 } _sifields;
96} compat_siginfo_t;
97
98/*
99 * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
100 */
101#define __NR_O32_sigreturn 4119
102#define __NR_O32_rt_sigreturn 4193
103#define __NR_O32_restart_syscall 4253
104
105#define DEBUG_SIG 0
106
107#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
108
109extern int do_signal32(sigset_t *oldset, struct pt_regs *regs);
110
111/* 32-bit compatibility types */
112
113#define _NSIG_BPW32 32
114#define _NSIG_WORDS32 (_NSIG / _NSIG_BPW32)
115
116typedef struct {
117 unsigned int sig[_NSIG_WORDS32];
118} sigset_t32;
119
120typedef unsigned int __sighandler32_t;
121typedef void (*vfptr_t)(void);
122
123struct sigaction32 {
124 unsigned int sa_flags;
125 __sighandler32_t sa_handler;
126 compat_sigset_t sa_mask;
127};
128
129/* IRIX compatible stack_t */
130typedef struct sigaltstack32 {
131 s32 ss_sp;
132 compat_size_t ss_size;
133 int ss_flags;
134} stack32_t;
135
136struct ucontext32 {
137 u32 uc_flags;
138 s32 uc_link;
139 stack32_t uc_stack;
140 struct sigcontext32 uc_mcontext;
141 sigset_t32 uc_sigmask; /* mask last for extensibility */
142};
143
144extern void __put_sigset_unknown_nsig(void);
145extern void __get_sigset_unknown_nsig(void);
146
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900147static inline int put_sigset(const sigset_t *kbuf, compat_sigset_t __user *ubuf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148{
149 int err = 0;
150
151 if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)))
152 return -EFAULT;
153
154 switch (_NSIG_WORDS) {
155 default:
156 __put_sigset_unknown_nsig();
157 case 2:
158 err |= __put_user (kbuf->sig[1] >> 32, &ubuf->sig[3]);
159 err |= __put_user (kbuf->sig[1] & 0xffffffff, &ubuf->sig[2]);
160 case 1:
161 err |= __put_user (kbuf->sig[0] >> 32, &ubuf->sig[1]);
162 err |= __put_user (kbuf->sig[0] & 0xffffffff, &ubuf->sig[0]);
163 }
164
165 return err;
166}
167
168static inline int get_sigset(sigset_t *kbuf, const compat_sigset_t *ubuf)
169{
170 int err = 0;
171 unsigned long sig[4];
172
173 if (!access_ok(VERIFY_READ, ubuf, sizeof(*ubuf)))
174 return -EFAULT;
175
176 switch (_NSIG_WORDS) {
177 default:
178 __get_sigset_unknown_nsig();
179 case 2:
180 err |= __get_user (sig[3], &ubuf->sig[3]);
181 err |= __get_user (sig[2], &ubuf->sig[2]);
182 kbuf->sig[1] = sig[2] | (sig[3] << 32);
183 case 1:
184 err |= __get_user (sig[1], &ubuf->sig[1]);
185 err |= __get_user (sig[0], &ubuf->sig[0]);
186 kbuf->sig[0] = sig[0] | (sig[1] << 32);
187 }
188
189 return err;
190}
191
192/*
193 * Atomically swap in the new signal mask, and wait for a signal.
194 */
195
196save_static_function(sys32_sigsuspend);
197__attribute_used__ noinline static int
198_sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
199{
200 compat_sigset_t *uset;
201 sigset_t newset, saveset;
202
203 uset = (compat_sigset_t *) regs.regs[4];
204 if (get_sigset(&newset, uset))
205 return -EFAULT;
206 sigdelsetmask(&newset, ~_BLOCKABLE);
207
208 spin_lock_irq(&current->sighand->siglock);
209 saveset = current->blocked;
210 current->blocked = newset;
211 recalc_sigpending();
212 spin_unlock_irq(&current->sighand->siglock);
213
214 regs.regs[2] = EINTR;
215 regs.regs[7] = 1;
216 while (1) {
217 current->state = TASK_INTERRUPTIBLE;
218 schedule();
219 if (do_signal32(&saveset, &regs))
220 return -EINTR;
221 }
222}
223
224save_static_function(sys32_rt_sigsuspend);
225__attribute_used__ noinline static int
226_sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
227{
228 compat_sigset_t *uset;
229 sigset_t newset, saveset;
230 size_t sigsetsize;
231
232 /* XXX Don't preclude handling different sized sigset_t's. */
233 sigsetsize = regs.regs[5];
234 if (sigsetsize != sizeof(compat_sigset_t))
235 return -EINVAL;
236
237 uset = (compat_sigset_t *) regs.regs[4];
238 if (get_sigset(&newset, uset))
239 return -EFAULT;
240 sigdelsetmask(&newset, ~_BLOCKABLE);
241
242 spin_lock_irq(&current->sighand->siglock);
243 saveset = current->blocked;
244 current->blocked = newset;
245 recalc_sigpending();
246 spin_unlock_irq(&current->sighand->siglock);
247
248 regs.regs[2] = EINTR;
249 regs.regs[7] = 1;
250 while (1) {
251 current->state = TASK_INTERRUPTIBLE;
252 schedule();
253 if (do_signal32(&saveset, &regs))
254 return -EINTR;
255 }
256}
257
258asmlinkage int sys32_sigaction(int sig, const struct sigaction32 *act,
259 struct sigaction32 *oact)
260{
261 struct k_sigaction new_ka, old_ka;
262 int ret;
263 int err = 0;
264
265 if (act) {
266 old_sigset_t mask;
Ralf Baechle77c728c2005-03-04 19:36:51 +0000267 s32 handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268
269 if (!access_ok(VERIFY_READ, act, sizeof(*act)))
270 return -EFAULT;
Ralf Baechle77c728c2005-03-04 19:36:51 +0000271 err |= __get_user(handler, &act->sa_handler);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900272 new_ka.sa.sa_handler = (void __user *)(s64)handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
274 err |= __get_user(mask, &act->sa_mask.sig[0]);
275 if (err)
276 return -EFAULT;
277
278 siginitset(&new_ka.sa.sa_mask, mask);
279 }
280
281 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
282
283 if (!ret && oact) {
284 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
285 return -EFAULT;
286 err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
287 err |= __put_user((u32)(u64)old_ka.sa.sa_handler,
288 &oact->sa_handler);
289 err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
290 err |= __put_user(0, &oact->sa_mask.sig[1]);
291 err |= __put_user(0, &oact->sa_mask.sig[2]);
292 err |= __put_user(0, &oact->sa_mask.sig[3]);
293 if (err)
294 return -EFAULT;
295 }
296
297 return ret;
298}
299
300asmlinkage int sys32_sigaltstack(nabi_no_regargs struct pt_regs regs)
301{
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900302 const stack32_t __user *uss = (const stack32_t __user *) regs.regs[4];
303 stack32_t __user *uoss = (stack32_t __user *) regs.regs[5];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 unsigned long usp = regs.regs[29];
305 stack_t kss, koss;
306 int ret, err = 0;
307 mm_segment_t old_fs = get_fs();
308 s32 sp;
309
310 if (uss) {
311 if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
312 return -EFAULT;
313 err |= __get_user(sp, &uss->ss_sp);
314 kss.ss_sp = (void *) (long) sp;
315 err |= __get_user(kss.ss_size, &uss->ss_size);
316 err |= __get_user(kss.ss_flags, &uss->ss_flags);
317 if (err)
318 return -EFAULT;
319 }
320
321 set_fs (KERNEL_DS);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900322 ret = do_sigaltstack(uss ? (stack_t __user *)&kss : NULL,
323 uoss ? (stack_t __user *)&koss : NULL, usp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 set_fs (old_fs);
325
326 if (!ret && uoss) {
327 if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
328 return -EFAULT;
329 sp = (int) (long) koss.ss_sp;
330 err |= __put_user(sp, &uoss->ss_sp);
331 err |= __put_user(koss.ss_size, &uoss->ss_size);
332 err |= __put_user(koss.ss_flags, &uoss->ss_flags);
333 if (err)
334 return -EFAULT;
335 }
336 return ret;
337}
338
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900339static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 __user *sc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340{
Ralf Baechlee50c0a82005-05-31 11:49:19 +0000341 u32 used_math;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 int err = 0;
Ralf Baechlee50c0a82005-05-31 11:49:19 +0000343 s32 treg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344
345 /* Always make any pending restarted system calls return -EINTR */
346 current_thread_info()->restart_block.fn = do_no_restart_syscall;
347
348 err |= __get_user(regs->cp0_epc, &sc->sc_pc);
349 err |= __get_user(regs->hi, &sc->sc_mdhi);
350 err |= __get_user(regs->lo, &sc->sc_mdlo);
Ralf Baechlee50c0a82005-05-31 11:49:19 +0000351 if (cpu_has_dsp) {
352 err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
353 err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
354 err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
355 err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
356 err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
357 err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
358 err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
359 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360
361#define restore_gp_reg(i) do { \
362 err |= __get_user(regs->regs[i], &sc->sc_regs[i]); \
363} while(0)
364 restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
365 restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
366 restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
367 restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
368 restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
369 restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
370 restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
371 restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
372 restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
373 restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
374 restore_gp_reg(31);
375#undef restore_gp_reg
376
377 err |= __get_user(used_math, &sc->sc_used_math);
378 conditional_used_math(used_math);
379
380 preempt_disable();
381
382 if (used_math()) {
383 /* restore fpu context if we have used it before */
384 own_fpu();
385 err |= restore_fp_context32(sc);
386 } else {
387 /* signal handler may have used FPU. Give it up. */
388 lose_fpu();
389 }
390
391 preempt_enable();
392
393 return err;
394}
395
396struct sigframe {
397 u32 sf_ass[4]; /* argument save space for o32 */
Ralf Baechle02416dc2005-06-15 13:00:12 +0000398#if ICACHE_REFILLS_WORKAROUND_WAR
399 u32 sf_pad[2];
400#else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 u32 sf_code[2]; /* signal trampoline */
Ralf Baechle02416dc2005-06-15 13:00:12 +0000402#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 struct sigcontext32 sf_sc;
404 sigset_t sf_mask;
Ralf Baechle02416dc2005-06-15 13:00:12 +0000405#if ICACHE_REFILLS_WORKAROUND_WAR
406 u32 sf_code[8] ____cacheline_aligned; /* signal trampoline */
407#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408};
409
410struct rt_sigframe32 {
411 u32 rs_ass[4]; /* argument save space for o32 */
Ralf Baechle02416dc2005-06-15 13:00:12 +0000412#if ICACHE_REFILLS_WORKAROUND_WAR
413 u32 rs_pad[2];
414#else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 u32 rs_code[2]; /* signal trampoline */
Ralf Baechle02416dc2005-06-15 13:00:12 +0000416#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 compat_siginfo_t rs_info;
418 struct ucontext32 rs_uc;
Ralf Baechle02416dc2005-06-15 13:00:12 +0000419#if ICACHE_REFILLS_WORKAROUND_WAR
420 u32 rs_code[8] __attribute__((aligned(32))); /* signal trampoline */
421#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422};
423
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900424int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425{
426 int err;
427
428 if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
429 return -EFAULT;
430
431 /* If you change siginfo_t structure, please be sure
432 this code is fixed accordingly.
433 It should never copy any pad contained in the structure
434 to avoid security leaks, but must copy the generic
435 3 ints plus the relevant union member.
436 This routine must convert siginfo from 64bit to 32bit as well
437 at the same time. */
438 err = __put_user(from->si_signo, &to->si_signo);
439 err |= __put_user(from->si_errno, &to->si_errno);
440 err |= __put_user((short)from->si_code, &to->si_code);
441 if (from->si_code < 0)
442 err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
443 else {
444 switch (from->si_code >> 16) {
Ralf Baechlea9820992005-02-16 21:24:16 +0000445 case __SI_TIMER >> 16:
446 err |= __put_user(from->si_tid, &to->si_tid);
447 err |= __put_user(from->si_overrun, &to->si_overrun);
448 err |= __put_user(from->si_int, &to->si_int);
449 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 case __SI_CHLD >> 16:
451 err |= __put_user(from->si_utime, &to->si_utime);
452 err |= __put_user(from->si_stime, &to->si_stime);
453 err |= __put_user(from->si_status, &to->si_status);
454 default:
455 err |= __put_user(from->si_pid, &to->si_pid);
456 err |= __put_user(from->si_uid, &to->si_uid);
457 break;
458 case __SI_FAULT >> 16:
Atsushi Nemoto5665a0a2006-02-02 01:26:34 +0900459 err |= __put_user((unsigned long)from->si_addr, &to->si_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 break;
461 case __SI_POLL >> 16:
462 err |= __put_user(from->si_band, &to->si_band);
463 err |= __put_user(from->si_fd, &to->si_fd);
464 break;
465 case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
466 case __SI_MESGQ >> 16:
467 err |= __put_user(from->si_pid, &to->si_pid);
468 err |= __put_user(from->si_uid, &to->si_uid);
469 err |= __put_user(from->si_int, &to->si_int);
470 break;
471 }
472 }
473 return err;
474}
475
476save_static_function(sys32_sigreturn);
477__attribute_used__ noinline static void
478_sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
479{
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900480 struct sigframe __user *frame;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 sigset_t blocked;
482
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900483 frame = (struct sigframe __user *) regs.regs[29];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
485 goto badframe;
486 if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked)))
487 goto badframe;
488
489 sigdelsetmask(&blocked, ~_BLOCKABLE);
490 spin_lock_irq(&current->sighand->siglock);
491 current->blocked = blocked;
492 recalc_sigpending();
493 spin_unlock_irq(&current->sighand->siglock);
494
495 if (restore_sigcontext32(&regs, &frame->sf_sc))
496 goto badframe;
497
498 /*
499 * Don't let your children do this ...
500 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 __asm__ __volatile__(
502 "move\t$29, %0\n\t"
503 "j\tsyscall_exit"
504 :/* no outputs */
505 :"r" (&regs));
506 /* Unreached */
507
508badframe:
509 force_sig(SIGSEGV, current);
510}
511
512save_static_function(sys32_rt_sigreturn);
513__attribute_used__ noinline static void
514_sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
515{
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900516 struct rt_sigframe32 __user *frame;
Ralf Baechle1fcf1cc2005-04-13 18:18:04 +0000517 mm_segment_t old_fs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 sigset_t set;
519 stack_t st;
520 s32 sp;
521
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900522 frame = (struct rt_sigframe32 __user *) regs.regs[29];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
524 goto badframe;
525 if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
526 goto badframe;
527
528 sigdelsetmask(&set, ~_BLOCKABLE);
529 spin_lock_irq(&current->sighand->siglock);
530 current->blocked = set;
531 recalc_sigpending();
532 spin_unlock_irq(&current->sighand->siglock);
533
534 if (restore_sigcontext32(&regs, &frame->rs_uc.uc_mcontext))
535 goto badframe;
536
537 /* The ucontext contains a stack32_t, so we must convert! */
538 if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp))
539 goto badframe;
540 st.ss_size = (long) sp;
541 if (__get_user(st.ss_size, &frame->rs_uc.uc_stack.ss_size))
542 goto badframe;
543 if (__get_user(st.ss_flags, &frame->rs_uc.uc_stack.ss_flags))
544 goto badframe;
545
546 /* It is more difficult to avoid calling this function than to
547 call it and ignore errors. */
Ralf Baechle1fcf1cc2005-04-13 18:18:04 +0000548 old_fs = get_fs();
549 set_fs (KERNEL_DS);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900550 do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]);
Ralf Baechle1fcf1cc2005-04-13 18:18:04 +0000551 set_fs (old_fs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552
553 /*
554 * Don't let your children do this ...
555 */
556 __asm__ __volatile__(
557 "move\t$29, %0\n\t"
558 "j\tsyscall_exit"
559 :/* no outputs */
560 :"r" (&regs));
561 /* Unreached */
562
563badframe:
564 force_sig(SIGSEGV, current);
565}
566
567static inline int setup_sigcontext32(struct pt_regs *regs,
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900568 struct sigcontext32 __user *sc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569{
570 int err = 0;
571
572 err |= __put_user(regs->cp0_epc, &sc->sc_pc);
573 err |= __put_user(regs->cp0_status, &sc->sc_status);
574
575#define save_gp_reg(i) { \
576 err |= __put_user(regs->regs[i], &sc->sc_regs[i]); \
577} while(0)
578 __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
579 save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);
580 save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);
581 save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
582 save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18);
583 save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22);
584 save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
585 save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30);
586 save_gp_reg(31);
587#undef save_gp_reg
588
589 err |= __put_user(regs->hi, &sc->sc_mdhi);
590 err |= __put_user(regs->lo, &sc->sc_mdlo);
Ralf Baechlee50c0a82005-05-31 11:49:19 +0000591 if (cpu_has_dsp) {
Ralf Baechlec4fa6342005-12-07 17:50:48 +0000592 err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
Ralf Baechlee50c0a82005-05-31 11:49:19 +0000593 err |= __put_user(mfhi1(), &sc->sc_hi1);
594 err |= __put_user(mflo1(), &sc->sc_lo1);
595 err |= __put_user(mfhi2(), &sc->sc_hi2);
596 err |= __put_user(mflo2(), &sc->sc_lo2);
597 err |= __put_user(mfhi3(), &sc->sc_hi3);
598 err |= __put_user(mflo3(), &sc->sc_lo3);
599 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600
601 err |= __put_user(!!used_math(), &sc->sc_used_math);
602
603 if (!used_math())
604 goto out;
605
Ralf Baechle42a3b4f2005-09-03 15:56:17 -0700606 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 * Save FPU state to signal context. Signal handler will "inherit"
608 * current FPU state.
609 */
610 preempt_disable();
611
612 if (!is_fpu_owner()) {
613 own_fpu();
614 restore_fp(current);
615 }
616 err |= save_fp_context32(sc);
617
618 preempt_enable();
619
620out:
621 return err;
622}
623
624/*
625 * Determine which stack to use..
626 */
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900627static inline void __user *get_sigframe(struct k_sigaction *ka,
628 struct pt_regs *regs,
629 size_t frame_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630{
631 unsigned long sp;
632
633 /* Default to using normal stack */
634 sp = regs->regs[29];
635
636 /*
637 * FPU emulator may have it's own trampoline active just
638 * above the user stack, 16-bytes before the next lowest
639 * 16 byte boundary. Try to avoid trashing it.
640 */
641 sp -= 32;
642
643 /* This is the X/Open sanctioned signal stack switching. */
644 if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
645 sp = current->sas_ss_sp + current->sas_ss_size;
646
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900647 return (void __user *)((sp - frame_size) & ALMASK);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648}
649
Atsushi Nemoto16cd3952005-11-05 23:00:58 +0900650int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
651 int signr, sigset_t *set)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652{
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900653 struct sigframe __user *frame;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 int err = 0;
655
656 frame = get_sigframe(ka, regs, sizeof(*frame));
657 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
658 goto give_sigsegv;
659
660 /*
661 * Set up the return code ...
662 *
663 * li v0, __NR_O32_sigreturn
664 * syscall
665 */
666 err |= __put_user(0x24020000 + __NR_O32_sigreturn, frame->sf_code + 0);
667 err |= __put_user(0x0000000c , frame->sf_code + 1);
668 flush_cache_sigtramp((unsigned long) frame->sf_code);
669
670 err |= setup_sigcontext32(regs, &frame->sf_sc);
671 err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
672 if (err)
673 goto give_sigsegv;
674
675 /*
676 * Arguments to signal handler:
677 *
678 * a0 = signal number
679 * a1 = 0 (should be cause)
680 * a2 = pointer to struct sigcontext
681 *
682 * $25 and c0_epc point to the signal handler, $29 points to the
683 * struct sigframe.
684 */
685 regs->regs[ 4] = signr;
686 regs->regs[ 5] = 0;
687 regs->regs[ 6] = (unsigned long) &frame->sf_sc;
688 regs->regs[29] = (unsigned long) frame;
689 regs->regs[31] = (unsigned long) frame->sf_code;
690 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
691
692#if DEBUG_SIG
693 printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n",
694 current->comm, current->pid,
695 frame, regs->cp0_epc, frame->sf_code);
696#endif
Atsushi Nemoto16cd3952005-11-05 23:00:58 +0900697 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698
699give_sigsegv:
700 force_sigsegv(signr, current);
Atsushi Nemoto16cd3952005-11-05 23:00:58 +0900701 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702}
703
Atsushi Nemoto16cd3952005-11-05 23:00:58 +0900704int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
705 int signr, sigset_t *set, siginfo_t *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706{
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900707 struct rt_sigframe32 __user *frame;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 int err = 0;
709 s32 sp;
710
711 frame = get_sigframe(ka, regs, sizeof(*frame));
712 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
713 goto give_sigsegv;
714
715 /* Set up to return from userspace. If provided, use a stub already
716 in userspace. */
717 /*
718 * Set up the return code ...
719 *
720 * li v0, __NR_O32_rt_sigreturn
721 * syscall
722 */
723 err |= __put_user(0x24020000 + __NR_O32_rt_sigreturn, frame->rs_code + 0);
724 err |= __put_user(0x0000000c , frame->rs_code + 1);
725 flush_cache_sigtramp((unsigned long) frame->rs_code);
726
727 /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
728 err |= copy_siginfo_to_user32(&frame->rs_info, info);
729
730 /* Create the ucontext. */
731 err |= __put_user(0, &frame->rs_uc.uc_flags);
732 err |= __put_user(0, &frame->rs_uc.uc_link);
733 sp = (int) (long) current->sas_ss_sp;
734 err |= __put_user(sp,
735 &frame->rs_uc.uc_stack.ss_sp);
736 err |= __put_user(sas_ss_flags(regs->regs[29]),
737 &frame->rs_uc.uc_stack.ss_flags);
738 err |= __put_user(current->sas_ss_size,
739 &frame->rs_uc.uc_stack.ss_size);
740 err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext);
741 err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
742
743 if (err)
744 goto give_sigsegv;
745
746 /*
747 * Arguments to signal handler:
748 *
749 * a0 = signal number
750 * a1 = 0 (should be cause)
751 * a2 = pointer to ucontext
752 *
753 * $25 and c0_epc point to the signal handler, $29 points to
754 * the struct rt_sigframe32.
755 */
756 regs->regs[ 4] = signr;
757 regs->regs[ 5] = (unsigned long) &frame->rs_info;
758 regs->regs[ 6] = (unsigned long) &frame->rs_uc;
759 regs->regs[29] = (unsigned long) frame;
760 regs->regs[31] = (unsigned long) frame->rs_code;
761 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
762
763#if DEBUG_SIG
764 printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n",
765 current->comm, current->pid,
766 frame, regs->cp0_epc, frame->rs_code);
767#endif
Atsushi Nemoto16cd3952005-11-05 23:00:58 +0900768 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769
770give_sigsegv:
771 force_sigsegv(signr, current);
Atsushi Nemoto16cd3952005-11-05 23:00:58 +0900772 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773}
774
Ralf Baechle129bc8f2005-07-11 20:45:51 +0000775static inline int handle_signal(unsigned long sig, siginfo_t *info,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs)
777{
Ralf Baechle129bc8f2005-07-11 20:45:51 +0000778 int ret;
779
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 switch (regs->regs[0]) {
781 case ERESTART_RESTARTBLOCK:
782 case ERESTARTNOHAND:
783 regs->regs[2] = EINTR;
784 break;
785 case ERESTARTSYS:
786 if(!(ka->sa.sa_flags & SA_RESTART)) {
787 regs->regs[2] = EINTR;
788 break;
789 }
790 /* fallthrough */
791 case ERESTARTNOINTR: /* Userland will reload $v0. */
792 regs->regs[7] = regs->regs[26];
793 regs->cp0_epc -= 8;
794 }
795
796 regs->regs[0] = 0; /* Don't deal with this again. */
797
798 if (ka->sa.sa_flags & SA_SIGINFO)
Ralf Baechle129bc8f2005-07-11 20:45:51 +0000799 ret = current->thread.abi->setup_rt_frame(ka, regs, sig, oldset, info);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 else
Ralf Baechle129bc8f2005-07-11 20:45:51 +0000801 ret = current->thread.abi->setup_frame(ka, regs, sig, oldset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802
Steven Rostedt69be8f12005-08-29 11:44:09 -0400803 spin_lock_irq(&current->sighand->siglock);
804 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
805 if (!(ka->sa.sa_flags & SA_NODEFER))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 sigaddset(&current->blocked,sig);
Steven Rostedt69be8f12005-08-29 11:44:09 -0400807 recalc_sigpending();
808 spin_unlock_irq(&current->sighand->siglock);
Ralf Baechle129bc8f2005-07-11 20:45:51 +0000809
810 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811}
812
813int do_signal32(sigset_t *oldset, struct pt_regs *regs)
814{
815 struct k_sigaction ka;
816 siginfo_t info;
817 int signr;
818
819 /*
820 * We want the common case to go fast, which is why we may in certain
821 * cases get here from kernel mode. Just return without doing anything
822 * if so.
823 */
824 if (!user_mode(regs))
825 return 1;
826
Nigel Cunningham0e6c1f52005-07-27 11:43:34 -0700827 if (try_to_freeze())
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828 goto no_signal;
829
830 if (!oldset)
831 oldset = &current->blocked;
832
833 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
Ralf Baechle129bc8f2005-07-11 20:45:51 +0000834 if (signr > 0)
835 return handle_signal(signr, &info, &ka, oldset, regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836
837no_signal:
838 /*
839 * Who's code doesn't conform to the restartable syscall convention
840 * dies here!!! The li instruction, a single machine instruction,
841 * must directly be followed by the syscall instruction.
842 */
843 if (regs->regs[0]) {
844 if (regs->regs[2] == ERESTARTNOHAND ||
845 regs->regs[2] == ERESTARTSYS ||
846 regs->regs[2] == ERESTARTNOINTR) {
847 regs->regs[7] = regs->regs[26];
848 regs->cp0_epc -= 8;
849 }
850 if (regs->regs[2] == ERESTART_RESTARTBLOCK) {
851 regs->regs[2] = __NR_O32_restart_syscall;
852 regs->regs[7] = regs->regs[26];
853 regs->cp0_epc -= 4;
854 }
855 }
856 return 0;
857}
858
859asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 *act,
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900860 struct sigaction32 __user *oact,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 unsigned int sigsetsize)
862{
863 struct k_sigaction new_sa, old_sa;
864 int ret = -EINVAL;
865
866 /* XXX: Don't preclude handling different sized sigset_t's. */
867 if (sigsetsize != sizeof(sigset_t))
868 goto out;
869
870 if (act) {
Ralf Baechle77c728c2005-03-04 19:36:51 +0000871 s32 handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 int err = 0;
873
874 if (!access_ok(VERIFY_READ, act, sizeof(*act)))
875 return -EFAULT;
Ralf Baechle77c728c2005-03-04 19:36:51 +0000876 err |= __get_user(handler, &act->sa_handler);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900877 new_sa.sa.sa_handler = (void __user *)(s64)handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 err |= __get_user(new_sa.sa.sa_flags, &act->sa_flags);
879 err |= get_sigset(&new_sa.sa.sa_mask, &act->sa_mask);
880 if (err)
881 return -EFAULT;
882 }
883
884 ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
885
886 if (!ret && oact) {
887 int err = 0;
888
889 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
890 return -EFAULT;
891
892 err |= __put_user((u32)(u64)old_sa.sa.sa_handler,
893 &oact->sa_handler);
894 err |= __put_user(old_sa.sa.sa_flags, &oact->sa_flags);
895 err |= put_sigset(&old_sa.sa.sa_mask, &oact->sa_mask);
896 if (err)
897 return -EFAULT;
898 }
899out:
900 return ret;
901}
902
903asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t *set,
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900904 compat_sigset_t __user *oset, unsigned int sigsetsize)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905{
906 sigset_t old_set, new_set;
907 int ret;
908 mm_segment_t old_fs = get_fs();
909
910 if (set && get_sigset(&new_set, set))
911 return -EFAULT;
912
913 set_fs (KERNEL_DS);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900914 ret = sys_rt_sigprocmask(how, set ? (sigset_t __user *)&new_set : NULL,
915 oset ? (sigset_t __user *)&old_set : NULL,
916 sigsetsize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 set_fs (old_fs);
918
919 if (!ret && oset && put_sigset(&old_set, oset))
920 return -EFAULT;
921
922 return ret;
923}
924
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900925asmlinkage int sys32_rt_sigpending(compat_sigset_t __user *uset,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 unsigned int sigsetsize)
927{
928 int ret;
929 sigset_t set;
930 mm_segment_t old_fs = get_fs();
931
932 set_fs (KERNEL_DS);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900933 ret = sys_rt_sigpending((sigset_t __user *)&set, sigsetsize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 set_fs (old_fs);
935
936 if (!ret && put_sigset(&set, uset))
937 return -EFAULT;
938
939 return ret;
940}
941
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900942asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943{
944 siginfo_t info;
945 int ret;
946 mm_segment_t old_fs = get_fs();
947
948 if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
949 copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
950 return -EFAULT;
951 set_fs (KERNEL_DS);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900952 ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *)&info);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 set_fs (old_fs);
954 return ret;
955}
Ralf Baechle54f2da72005-02-16 21:21:29 +0000956
957asmlinkage long
958sys32_waitid(int which, compat_pid_t pid,
959 compat_siginfo_t __user *uinfo, int options,
960 struct compat_rusage __user *uru)
961{
962 siginfo_t info;
963 struct rusage ru;
964 long ret;
965 mm_segment_t old_fs = get_fs();
966
967 info.si_signo = 0;
968 set_fs (KERNEL_DS);
969 ret = sys_waitid(which, pid, (siginfo_t __user *) &info, options,
970 uru ? (struct rusage __user *) &ru : NULL);
971 set_fs (old_fs);
972
973 if (ret < 0 || info.si_signo == 0)
974 return ret;
975
976 if (uru && (ret = put_compat_rusage(&ru, uru)))
977 return ret;
978
979 BUG_ON(info.si_code & __SI_MASK);
980 info.si_code |= __SI_CHLD;
981 return copy_siginfo_to_user32(uinfo, &info);
982}