blob: 98b185bbc947c0576851787a78836927f5b9d65e [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
147static inline int put_sigset(const sigset_t *kbuf, compat_sigset_t *ubuf)
148{
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);
272 new_ka.sa.sa_handler = (void*)(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{
302 const stack32_t *uss = (const stack32_t *) regs.regs[4];
303 stack32_t *uoss = (stack32_t *) regs.regs[5];
304 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);
322 ret = do_sigaltstack(uss ? &kss : NULL , uoss ? &koss : NULL, usp);
323 set_fs (old_fs);
324
325 if (!ret && uoss) {
326 if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
327 return -EFAULT;
328 sp = (int) (long) koss.ss_sp;
329 err |= __put_user(sp, &uoss->ss_sp);
330 err |= __put_user(koss.ss_size, &uoss->ss_size);
331 err |= __put_user(koss.ss_flags, &uoss->ss_flags);
332 if (err)
333 return -EFAULT;
334 }
335 return ret;
336}
337
338static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 *sc)
339{
Ralf Baechlee50c0a82005-05-31 11:49:19 +0000340 u32 used_math;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 int err = 0;
Ralf Baechlee50c0a82005-05-31 11:49:19 +0000342 s32 treg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343
344 /* Always make any pending restarted system calls return -EINTR */
345 current_thread_info()->restart_block.fn = do_no_restart_syscall;
346
347 err |= __get_user(regs->cp0_epc, &sc->sc_pc);
348 err |= __get_user(regs->hi, &sc->sc_mdhi);
349 err |= __get_user(regs->lo, &sc->sc_mdlo);
Ralf Baechlee50c0a82005-05-31 11:49:19 +0000350 if (cpu_has_dsp) {
351 err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
352 err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
353 err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
354 err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
355 err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
356 err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
357 err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
358 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359
360#define restore_gp_reg(i) do { \
361 err |= __get_user(regs->regs[i], &sc->sc_regs[i]); \
362} while(0)
363 restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
364 restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
365 restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
366 restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
367 restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
368 restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
369 restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
370 restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
371 restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
372 restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
373 restore_gp_reg(31);
374#undef restore_gp_reg
375
376 err |= __get_user(used_math, &sc->sc_used_math);
377 conditional_used_math(used_math);
378
379 preempt_disable();
380
381 if (used_math()) {
382 /* restore fpu context if we have used it before */
383 own_fpu();
384 err |= restore_fp_context32(sc);
385 } else {
386 /* signal handler may have used FPU. Give it up. */
387 lose_fpu();
388 }
389
390 preempt_enable();
391
392 return err;
393}
394
395struct sigframe {
396 u32 sf_ass[4]; /* argument save space for o32 */
Ralf Baechle02416dc2005-06-15 13:00:12 +0000397#if ICACHE_REFILLS_WORKAROUND_WAR
398 u32 sf_pad[2];
399#else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 u32 sf_code[2]; /* signal trampoline */
Ralf Baechle02416dc2005-06-15 13:00:12 +0000401#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 struct sigcontext32 sf_sc;
403 sigset_t sf_mask;
Ralf Baechle02416dc2005-06-15 13:00:12 +0000404#if ICACHE_REFILLS_WORKAROUND_WAR
405 u32 sf_code[8] ____cacheline_aligned; /* signal trampoline */
406#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407};
408
409struct rt_sigframe32 {
410 u32 rs_ass[4]; /* argument save space for o32 */
Ralf Baechle02416dc2005-06-15 13:00:12 +0000411#if ICACHE_REFILLS_WORKAROUND_WAR
412 u32 rs_pad[2];
413#else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 u32 rs_code[2]; /* signal trampoline */
Ralf Baechle02416dc2005-06-15 13:00:12 +0000415#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 compat_siginfo_t rs_info;
417 struct ucontext32 rs_uc;
Ralf Baechle02416dc2005-06-15 13:00:12 +0000418#if ICACHE_REFILLS_WORKAROUND_WAR
419 u32 rs_code[8] __attribute__((aligned(32))); /* signal trampoline */
420#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421};
422
423int copy_siginfo_to_user32(compat_siginfo_t *to, siginfo_t *from)
424{
425 int err;
426
427 if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
428 return -EFAULT;
429
430 /* If you change siginfo_t structure, please be sure
431 this code is fixed accordingly.
432 It should never copy any pad contained in the structure
433 to avoid security leaks, but must copy the generic
434 3 ints plus the relevant union member.
435 This routine must convert siginfo from 64bit to 32bit as well
436 at the same time. */
437 err = __put_user(from->si_signo, &to->si_signo);
438 err |= __put_user(from->si_errno, &to->si_errno);
439 err |= __put_user((short)from->si_code, &to->si_code);
440 if (from->si_code < 0)
441 err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
442 else {
443 switch (from->si_code >> 16) {
Ralf Baechlea9820992005-02-16 21:24:16 +0000444 case __SI_TIMER >> 16:
445 err |= __put_user(from->si_tid, &to->si_tid);
446 err |= __put_user(from->si_overrun, &to->si_overrun);
447 err |= __put_user(from->si_int, &to->si_int);
448 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 case __SI_CHLD >> 16:
450 err |= __put_user(from->si_utime, &to->si_utime);
451 err |= __put_user(from->si_stime, &to->si_stime);
452 err |= __put_user(from->si_status, &to->si_status);
453 default:
454 err |= __put_user(from->si_pid, &to->si_pid);
455 err |= __put_user(from->si_uid, &to->si_uid);
456 break;
457 case __SI_FAULT >> 16:
458 err |= __put_user((long)from->si_addr, &to->si_addr);
459 break;
460 case __SI_POLL >> 16:
461 err |= __put_user(from->si_band, &to->si_band);
462 err |= __put_user(from->si_fd, &to->si_fd);
463 break;
464 case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
465 case __SI_MESGQ >> 16:
466 err |= __put_user(from->si_pid, &to->si_pid);
467 err |= __put_user(from->si_uid, &to->si_uid);
468 err |= __put_user(from->si_int, &to->si_int);
469 break;
470 }
471 }
472 return err;
473}
474
475save_static_function(sys32_sigreturn);
476__attribute_used__ noinline static void
477_sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
478{
479 struct sigframe *frame;
480 sigset_t blocked;
481
482 frame = (struct sigframe *) regs.regs[29];
483 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
484 goto badframe;
485 if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked)))
486 goto badframe;
487
488 sigdelsetmask(&blocked, ~_BLOCKABLE);
489 spin_lock_irq(&current->sighand->siglock);
490 current->blocked = blocked;
491 recalc_sigpending();
492 spin_unlock_irq(&current->sighand->siglock);
493
494 if (restore_sigcontext32(&regs, &frame->sf_sc))
495 goto badframe;
496
497 /*
498 * Don't let your children do this ...
499 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 __asm__ __volatile__(
501 "move\t$29, %0\n\t"
502 "j\tsyscall_exit"
503 :/* no outputs */
504 :"r" (&regs));
505 /* Unreached */
506
507badframe:
508 force_sig(SIGSEGV, current);
509}
510
511save_static_function(sys32_rt_sigreturn);
512__attribute_used__ noinline static void
513_sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
514{
515 struct rt_sigframe32 *frame;
Ralf Baechle1fcf1cc2005-04-13 18:18:04 +0000516 mm_segment_t old_fs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 sigset_t set;
518 stack_t st;
519 s32 sp;
520
521 frame = (struct rt_sigframe32 *) regs.regs[29];
522 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
523 goto badframe;
524 if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
525 goto badframe;
526
527 sigdelsetmask(&set, ~_BLOCKABLE);
528 spin_lock_irq(&current->sighand->siglock);
529 current->blocked = set;
530 recalc_sigpending();
531 spin_unlock_irq(&current->sighand->siglock);
532
533 if (restore_sigcontext32(&regs, &frame->rs_uc.uc_mcontext))
534 goto badframe;
535
536 /* The ucontext contains a stack32_t, so we must convert! */
537 if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp))
538 goto badframe;
539 st.ss_size = (long) sp;
540 if (__get_user(st.ss_size, &frame->rs_uc.uc_stack.ss_size))
541 goto badframe;
542 if (__get_user(st.ss_flags, &frame->rs_uc.uc_stack.ss_flags))
543 goto badframe;
544
545 /* It is more difficult to avoid calling this function than to
546 call it and ignore errors. */
Ralf Baechle1fcf1cc2005-04-13 18:18:04 +0000547 old_fs = get_fs();
548 set_fs (KERNEL_DS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 do_sigaltstack(&st, NULL, regs.regs[29]);
Ralf Baechle1fcf1cc2005-04-13 18:18:04 +0000550 set_fs (old_fs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551
552 /*
553 * Don't let your children do this ...
554 */
555 __asm__ __volatile__(
556 "move\t$29, %0\n\t"
557 "j\tsyscall_exit"
558 :/* no outputs */
559 :"r" (&regs));
560 /* Unreached */
561
562badframe:
563 force_sig(SIGSEGV, current);
564}
565
566static inline int setup_sigcontext32(struct pt_regs *regs,
567 struct sigcontext32 *sc)
568{
569 int err = 0;
570
571 err |= __put_user(regs->cp0_epc, &sc->sc_pc);
572 err |= __put_user(regs->cp0_status, &sc->sc_status);
573
574#define save_gp_reg(i) { \
575 err |= __put_user(regs->regs[i], &sc->sc_regs[i]); \
576} while(0)
577 __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
578 save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);
579 save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);
580 save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
581 save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18);
582 save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22);
583 save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
584 save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30);
585 save_gp_reg(31);
586#undef save_gp_reg
587
588 err |= __put_user(regs->hi, &sc->sc_mdhi);
589 err |= __put_user(regs->lo, &sc->sc_mdlo);
Ralf Baechlee50c0a82005-05-31 11:49:19 +0000590 if (cpu_has_dsp) {
Ralf Baechlec4fa6342005-12-07 17:50:48 +0000591 err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
Ralf Baechlee50c0a82005-05-31 11:49:19 +0000592 err |= __put_user(mfhi1(), &sc->sc_hi1);
593 err |= __put_user(mflo1(), &sc->sc_lo1);
594 err |= __put_user(mfhi2(), &sc->sc_hi2);
595 err |= __put_user(mflo2(), &sc->sc_lo2);
596 err |= __put_user(mfhi3(), &sc->sc_hi3);
597 err |= __put_user(mflo3(), &sc->sc_lo3);
598 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599
600 err |= __put_user(!!used_math(), &sc->sc_used_math);
601
602 if (!used_math())
603 goto out;
604
Ralf Baechle42a3b4f2005-09-03 15:56:17 -0700605 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 * Save FPU state to signal context. Signal handler will "inherit"
607 * current FPU state.
608 */
609 preempt_disable();
610
611 if (!is_fpu_owner()) {
612 own_fpu();
613 restore_fp(current);
614 }
615 err |= save_fp_context32(sc);
616
617 preempt_enable();
618
619out:
620 return err;
621}
622
623/*
624 * Determine which stack to use..
625 */
626static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
627 size_t frame_size)
628{
629 unsigned long sp;
630
631 /* Default to using normal stack */
632 sp = regs->regs[29];
633
634 /*
635 * FPU emulator may have it's own trampoline active just
636 * above the user stack, 16-bytes before the next lowest
637 * 16 byte boundary. Try to avoid trashing it.
638 */
639 sp -= 32;
640
641 /* This is the X/Open sanctioned signal stack switching. */
642 if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
643 sp = current->sas_ss_sp + current->sas_ss_size;
644
645 return (void *)((sp - frame_size) & ALMASK);
646}
647
Atsushi Nemoto16cd3952005-11-05 23:00:58 +0900648int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
649 int signr, sigset_t *set)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650{
651 struct sigframe *frame;
652 int err = 0;
653
654 frame = get_sigframe(ka, regs, sizeof(*frame));
655 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
656 goto give_sigsegv;
657
658 /*
659 * Set up the return code ...
660 *
661 * li v0, __NR_O32_sigreturn
662 * syscall
663 */
664 err |= __put_user(0x24020000 + __NR_O32_sigreturn, frame->sf_code + 0);
665 err |= __put_user(0x0000000c , frame->sf_code + 1);
666 flush_cache_sigtramp((unsigned long) frame->sf_code);
667
668 err |= setup_sigcontext32(regs, &frame->sf_sc);
669 err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
670 if (err)
671 goto give_sigsegv;
672
673 /*
674 * Arguments to signal handler:
675 *
676 * a0 = signal number
677 * a1 = 0 (should be cause)
678 * a2 = pointer to struct sigcontext
679 *
680 * $25 and c0_epc point to the signal handler, $29 points to the
681 * struct sigframe.
682 */
683 regs->regs[ 4] = signr;
684 regs->regs[ 5] = 0;
685 regs->regs[ 6] = (unsigned long) &frame->sf_sc;
686 regs->regs[29] = (unsigned long) frame;
687 regs->regs[31] = (unsigned long) frame->sf_code;
688 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
689
690#if DEBUG_SIG
691 printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n",
692 current->comm, current->pid,
693 frame, regs->cp0_epc, frame->sf_code);
694#endif
Atsushi Nemoto16cd3952005-11-05 23:00:58 +0900695 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696
697give_sigsegv:
698 force_sigsegv(signr, current);
Atsushi Nemoto16cd3952005-11-05 23:00:58 +0900699 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700}
701
Atsushi Nemoto16cd3952005-11-05 23:00:58 +0900702int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
703 int signr, sigset_t *set, siginfo_t *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704{
705 struct rt_sigframe32 *frame;
706 int err = 0;
707 s32 sp;
708
709 frame = get_sigframe(ka, regs, sizeof(*frame));
710 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
711 goto give_sigsegv;
712
713 /* Set up to return from userspace. If provided, use a stub already
714 in userspace. */
715 /*
716 * Set up the return code ...
717 *
718 * li v0, __NR_O32_rt_sigreturn
719 * syscall
720 */
721 err |= __put_user(0x24020000 + __NR_O32_rt_sigreturn, frame->rs_code + 0);
722 err |= __put_user(0x0000000c , frame->rs_code + 1);
723 flush_cache_sigtramp((unsigned long) frame->rs_code);
724
725 /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
726 err |= copy_siginfo_to_user32(&frame->rs_info, info);
727
728 /* Create the ucontext. */
729 err |= __put_user(0, &frame->rs_uc.uc_flags);
730 err |= __put_user(0, &frame->rs_uc.uc_link);
731 sp = (int) (long) current->sas_ss_sp;
732 err |= __put_user(sp,
733 &frame->rs_uc.uc_stack.ss_sp);
734 err |= __put_user(sas_ss_flags(regs->regs[29]),
735 &frame->rs_uc.uc_stack.ss_flags);
736 err |= __put_user(current->sas_ss_size,
737 &frame->rs_uc.uc_stack.ss_size);
738 err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext);
739 err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
740
741 if (err)
742 goto give_sigsegv;
743
744 /*
745 * Arguments to signal handler:
746 *
747 * a0 = signal number
748 * a1 = 0 (should be cause)
749 * a2 = pointer to ucontext
750 *
751 * $25 and c0_epc point to the signal handler, $29 points to
752 * the struct rt_sigframe32.
753 */
754 regs->regs[ 4] = signr;
755 regs->regs[ 5] = (unsigned long) &frame->rs_info;
756 regs->regs[ 6] = (unsigned long) &frame->rs_uc;
757 regs->regs[29] = (unsigned long) frame;
758 regs->regs[31] = (unsigned long) frame->rs_code;
759 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
760
761#if DEBUG_SIG
762 printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n",
763 current->comm, current->pid,
764 frame, regs->cp0_epc, frame->rs_code);
765#endif
Atsushi Nemoto16cd3952005-11-05 23:00:58 +0900766 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767
768give_sigsegv:
769 force_sigsegv(signr, current);
Atsushi Nemoto16cd3952005-11-05 23:00:58 +0900770 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771}
772
Ralf Baechle129bc8f2005-07-11 20:45:51 +0000773static inline int handle_signal(unsigned long sig, siginfo_t *info,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs)
775{
Ralf Baechle129bc8f2005-07-11 20:45:51 +0000776 int ret;
777
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 switch (regs->regs[0]) {
779 case ERESTART_RESTARTBLOCK:
780 case ERESTARTNOHAND:
781 regs->regs[2] = EINTR;
782 break;
783 case ERESTARTSYS:
784 if(!(ka->sa.sa_flags & SA_RESTART)) {
785 regs->regs[2] = EINTR;
786 break;
787 }
788 /* fallthrough */
789 case ERESTARTNOINTR: /* Userland will reload $v0. */
790 regs->regs[7] = regs->regs[26];
791 regs->cp0_epc -= 8;
792 }
793
794 regs->regs[0] = 0; /* Don't deal with this again. */
795
796 if (ka->sa.sa_flags & SA_SIGINFO)
Ralf Baechle129bc8f2005-07-11 20:45:51 +0000797 ret = current->thread.abi->setup_rt_frame(ka, regs, sig, oldset, info);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 else
Ralf Baechle129bc8f2005-07-11 20:45:51 +0000799 ret = current->thread.abi->setup_frame(ka, regs, sig, oldset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800
Steven Rostedt69be8f12005-08-29 11:44:09 -0400801 spin_lock_irq(&current->sighand->siglock);
802 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
803 if (!(ka->sa.sa_flags & SA_NODEFER))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 sigaddset(&current->blocked,sig);
Steven Rostedt69be8f12005-08-29 11:44:09 -0400805 recalc_sigpending();
806 spin_unlock_irq(&current->sighand->siglock);
Ralf Baechle129bc8f2005-07-11 20:45:51 +0000807
808 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809}
810
811int do_signal32(sigset_t *oldset, struct pt_regs *regs)
812{
813 struct k_sigaction ka;
814 siginfo_t info;
815 int signr;
816
817 /*
818 * We want the common case to go fast, which is why we may in certain
819 * cases get here from kernel mode. Just return without doing anything
820 * if so.
821 */
822 if (!user_mode(regs))
823 return 1;
824
Nigel Cunningham0e6c1f52005-07-27 11:43:34 -0700825 if (try_to_freeze())
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 goto no_signal;
827
828 if (!oldset)
829 oldset = &current->blocked;
830
831 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
Ralf Baechle129bc8f2005-07-11 20:45:51 +0000832 if (signr > 0)
833 return handle_signal(signr, &info, &ka, oldset, regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834
835no_signal:
836 /*
837 * Who's code doesn't conform to the restartable syscall convention
838 * dies here!!! The li instruction, a single machine instruction,
839 * must directly be followed by the syscall instruction.
840 */
841 if (regs->regs[0]) {
842 if (regs->regs[2] == ERESTARTNOHAND ||
843 regs->regs[2] == ERESTARTSYS ||
844 regs->regs[2] == ERESTARTNOINTR) {
845 regs->regs[7] = regs->regs[26];
846 regs->cp0_epc -= 8;
847 }
848 if (regs->regs[2] == ERESTART_RESTARTBLOCK) {
849 regs->regs[2] = __NR_O32_restart_syscall;
850 regs->regs[7] = regs->regs[26];
851 regs->cp0_epc -= 4;
852 }
853 }
854 return 0;
855}
856
857asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 *act,
858 struct sigaction32 *oact,
859 unsigned int sigsetsize)
860{
861 struct k_sigaction new_sa, old_sa;
862 int ret = -EINVAL;
863
864 /* XXX: Don't preclude handling different sized sigset_t's. */
865 if (sigsetsize != sizeof(sigset_t))
866 goto out;
867
868 if (act) {
Ralf Baechle77c728c2005-03-04 19:36:51 +0000869 s32 handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 int err = 0;
871
872 if (!access_ok(VERIFY_READ, act, sizeof(*act)))
873 return -EFAULT;
Ralf Baechle77c728c2005-03-04 19:36:51 +0000874 err |= __get_user(handler, &act->sa_handler);
875 new_sa.sa.sa_handler = (void*)(s64)handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 err |= __get_user(new_sa.sa.sa_flags, &act->sa_flags);
877 err |= get_sigset(&new_sa.sa.sa_mask, &act->sa_mask);
878 if (err)
879 return -EFAULT;
880 }
881
882 ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
883
884 if (!ret && oact) {
885 int err = 0;
886
887 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
888 return -EFAULT;
889
890 err |= __put_user((u32)(u64)old_sa.sa.sa_handler,
891 &oact->sa_handler);
892 err |= __put_user(old_sa.sa.sa_flags, &oact->sa_flags);
893 err |= put_sigset(&old_sa.sa.sa_mask, &oact->sa_mask);
894 if (err)
895 return -EFAULT;
896 }
897out:
898 return ret;
899}
900
901asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t *set,
902 compat_sigset_t *oset, unsigned int sigsetsize)
903{
904 sigset_t old_set, new_set;
905 int ret;
906 mm_segment_t old_fs = get_fs();
907
908 if (set && get_sigset(&new_set, set))
909 return -EFAULT;
910
911 set_fs (KERNEL_DS);
912 ret = sys_rt_sigprocmask(how, set ? &new_set : NULL,
913 oset ? &old_set : NULL, sigsetsize);
914 set_fs (old_fs);
915
916 if (!ret && oset && put_sigset(&old_set, oset))
917 return -EFAULT;
918
919 return ret;
920}
921
922asmlinkage int sys32_rt_sigpending(compat_sigset_t *uset,
923 unsigned int sigsetsize)
924{
925 int ret;
926 sigset_t set;
927 mm_segment_t old_fs = get_fs();
928
929 set_fs (KERNEL_DS);
930 ret = sys_rt_sigpending(&set, sigsetsize);
931 set_fs (old_fs);
932
933 if (!ret && put_sigset(&set, uset))
934 return -EFAULT;
935
936 return ret;
937}
938
939asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t *uinfo)
940{
941 siginfo_t info;
942 int ret;
943 mm_segment_t old_fs = get_fs();
944
945 if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
946 copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
947 return -EFAULT;
948 set_fs (KERNEL_DS);
949 ret = sys_rt_sigqueueinfo(pid, sig, &info);
950 set_fs (old_fs);
951 return ret;
952}
Ralf Baechle54f2da72005-02-16 21:21:29 +0000953
954asmlinkage long
955sys32_waitid(int which, compat_pid_t pid,
956 compat_siginfo_t __user *uinfo, int options,
957 struct compat_rusage __user *uru)
958{
959 siginfo_t info;
960 struct rusage ru;
961 long ret;
962 mm_segment_t old_fs = get_fs();
963
964 info.si_signo = 0;
965 set_fs (KERNEL_DS);
966 ret = sys_waitid(which, pid, (siginfo_t __user *) &info, options,
967 uru ? (struct rusage __user *) &ru : NULL);
968 set_fs (old_fs);
969
970 if (ret < 0 || info.si_signo == 0)
971 return ret;
972
973 if (uru && (ret = put_compat_rusage(&ru, uru)))
974 return ret;
975
976 BUG_ON(info.si_code & __SI_MASK);
977 info.si_code |= __SI_CHLD;
978 return copy_siginfo_to_user32(uinfo, &info);
979}