PageRenderTime 64ms CodeModel.GetById 2ms app.highlight 55ms RepoModel.GetById 1ms app.codeStats 1ms

/arch/mips/kernel/signal32.c

https://bitbucket.org/evzijst/gittest
C | 905 lines | 656 code | 141 blank | 108 comment | 83 complexity | 2122597082e0bbefe218ae049026fa09 MD5 | raw file
  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}