aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/signal32.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/signal32.c')
-rw-r--r--arch/mips/kernel/signal32.c114
1 files changed, 94 insertions, 20 deletions
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index 8ddfbd8d425a..dbe821303125 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -7,6 +7,7 @@
7 * Copyright (C) 1994 - 2000 Ralf Baechle 7 * Copyright (C) 1994 - 2000 Ralf Baechle
8 * Copyright (C) 1999, 2000 Silicon Graphics, Inc. 8 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
9 */ 9 */
10#include <linux/cache.h>
10#include <linux/sched.h> 11#include <linux/sched.h>
11#include <linux/mm.h> 12#include <linux/mm.h>
12#include <linux/smp.h> 13#include <linux/smp.h>
@@ -21,6 +22,7 @@
21#include <linux/suspend.h> 22#include <linux/suspend.h>
22#include <linux/compiler.h> 23#include <linux/compiler.h>
23 24
25#include <asm/abi.h>
24#include <asm/asm.h> 26#include <asm/asm.h>
25#include <linux/bitops.h> 27#include <linux/bitops.h>
26#include <asm/cacheflush.h> 28#include <asm/cacheflush.h>
@@ -29,6 +31,7 @@
29#include <asm/ucontext.h> 31#include <asm/ucontext.h>
30#include <asm/system.h> 32#include <asm/system.h>
31#include <asm/fpu.h> 33#include <asm/fpu.h>
34#include <asm/war.h>
32 35
33#define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3) 36#define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3)
34 37
@@ -76,8 +79,10 @@ typedef struct compat_siginfo {
76 79
77 /* POSIX.1b timers */ 80 /* POSIX.1b timers */
78 struct { 81 struct {
79 unsigned int _timer1; 82 timer_t _tid; /* timer id */
80 unsigned int _timer2; 83 int _overrun; /* overrun count */
84 compat_sigval_t _sigval;/* same as below */
85 int _sys_private; /* not to be passed to user */
81 } _timer; 86 } _timer;
82 87
83 /* POSIX.1b signals */ 88 /* POSIX.1b signals */
@@ -259,11 +264,12 @@ asmlinkage int sys32_sigaction(int sig, const struct sigaction32 *act,
259 264
260 if (act) { 265 if (act) {
261 old_sigset_t mask; 266 old_sigset_t mask;
267 s32 handler;
262 268
263 if (!access_ok(VERIFY_READ, act, sizeof(*act))) 269 if (!access_ok(VERIFY_READ, act, sizeof(*act)))
264 return -EFAULT; 270 return -EFAULT;
265 err |= __get_user((u32)(u64)new_ka.sa.sa_handler, 271 err |= __get_user(handler, &act->sa_handler);
266 &act->sa_handler); 272 new_ka.sa.sa_handler = (void*)(s64)handler;
267 err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); 273 err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
268 err |= __get_user(mask, &act->sa_mask.sig[0]); 274 err |= __get_user(mask, &act->sa_mask.sig[0]);
269 if (err) 275 if (err)
@@ -331,8 +337,9 @@ asmlinkage int sys32_sigaltstack(nabi_no_regargs struct pt_regs regs)
331 337
332static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 *sc) 338static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 *sc)
333{ 339{
340 u32 used_math;
334 int err = 0; 341 int err = 0;
335 __u32 used_math; 342 s32 treg;
336 343
337 /* Always make any pending restarted system calls return -EINTR */ 344 /* Always make any pending restarted system calls return -EINTR */
338 current_thread_info()->restart_block.fn = do_no_restart_syscall; 345 current_thread_info()->restart_block.fn = do_no_restart_syscall;
@@ -340,6 +347,15 @@ static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 *sc)
340 err |= __get_user(regs->cp0_epc, &sc->sc_pc); 347 err |= __get_user(regs->cp0_epc, &sc->sc_pc);
341 err |= __get_user(regs->hi, &sc->sc_mdhi); 348 err |= __get_user(regs->hi, &sc->sc_mdhi);
342 err |= __get_user(regs->lo, &sc->sc_mdlo); 349 err |= __get_user(regs->lo, &sc->sc_mdlo);
350 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 }
343 359
344#define restore_gp_reg(i) do { \ 360#define restore_gp_reg(i) do { \
345 err |= __get_user(regs->regs[i], &sc->sc_regs[i]); \ 361 err |= __get_user(regs->regs[i], &sc->sc_regs[i]); \
@@ -378,16 +394,30 @@ static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 *sc)
378 394
379struct sigframe { 395struct sigframe {
380 u32 sf_ass[4]; /* argument save space for o32 */ 396 u32 sf_ass[4]; /* argument save space for o32 */
397#if ICACHE_REFILLS_WORKAROUND_WAR
398 u32 sf_pad[2];
399#else
381 u32 sf_code[2]; /* signal trampoline */ 400 u32 sf_code[2]; /* signal trampoline */
401#endif
382 struct sigcontext32 sf_sc; 402 struct sigcontext32 sf_sc;
383 sigset_t sf_mask; 403 sigset_t sf_mask;
404#if ICACHE_REFILLS_WORKAROUND_WAR
405 u32 sf_code[8] ____cacheline_aligned; /* signal trampoline */
406#endif
384}; 407};
385 408
386struct rt_sigframe32 { 409struct rt_sigframe32 {
387 u32 rs_ass[4]; /* argument save space for o32 */ 410 u32 rs_ass[4]; /* argument save space for o32 */
411#if ICACHE_REFILLS_WORKAROUND_WAR
412 u32 rs_pad[2];
413#else
388 u32 rs_code[2]; /* signal trampoline */ 414 u32 rs_code[2]; /* signal trampoline */
415#endif
389 compat_siginfo_t rs_info; 416 compat_siginfo_t rs_info;
390 struct ucontext32 rs_uc; 417 struct ucontext32 rs_uc;
418#if ICACHE_REFILLS_WORKAROUND_WAR
419 u32 rs_code[8] __attribute__((aligned(32))); /* signal trampoline */
420#endif
391}; 421};
392 422
393int copy_siginfo_to_user32(compat_siginfo_t *to, siginfo_t *from) 423int copy_siginfo_to_user32(compat_siginfo_t *to, siginfo_t *from)
@@ -411,6 +441,11 @@ int copy_siginfo_to_user32(compat_siginfo_t *to, siginfo_t *from)
411 err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE); 441 err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
412 else { 442 else {
413 switch (from->si_code >> 16) { 443 switch (from->si_code >> 16) {
444 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;
414 case __SI_CHLD >> 16: 449 case __SI_CHLD >> 16:
415 err |= __put_user(from->si_utime, &to->si_utime); 450 err |= __put_user(from->si_utime, &to->si_utime);
416 err |= __put_user(from->si_stime, &to->si_stime); 451 err |= __put_user(from->si_stime, &to->si_stime);
@@ -480,6 +515,7 @@ __attribute_used__ noinline static void
480_sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) 515_sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
481{ 516{
482 struct rt_sigframe32 *frame; 517 struct rt_sigframe32 *frame;
518 mm_segment_t old_fs;
483 sigset_t set; 519 sigset_t set;
484 stack_t st; 520 stack_t st;
485 s32 sp; 521 s32 sp;
@@ -510,7 +546,10 @@ _sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
510 546
511 /* It is more difficult to avoid calling this function than to 547 /* It is more difficult to avoid calling this function than to
512 call it and ignore errors. */ 548 call it and ignore errors. */
549 old_fs = get_fs();
550 set_fs (KERNEL_DS);
513 do_sigaltstack(&st, NULL, regs.regs[29]); 551 do_sigaltstack(&st, NULL, regs.regs[29]);
552 set_fs (old_fs);
514 553
515 /* 554 /*
516 * Don't let your children do this ... 555 * Don't let your children do this ...
@@ -550,8 +589,15 @@ static inline int setup_sigcontext32(struct pt_regs *regs,
550 589
551 err |= __put_user(regs->hi, &sc->sc_mdhi); 590 err |= __put_user(regs->hi, &sc->sc_mdhi);
552 err |= __put_user(regs->lo, &sc->sc_mdlo); 591 err |= __put_user(regs->lo, &sc->sc_mdlo);
553 err |= __put_user(regs->cp0_cause, &sc->sc_cause); 592 if (cpu_has_dsp) {
554 err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr); 593 err |= __put_user(rddsp(DSP_MASK), &sc->sc_hi1);
594 err |= __put_user(mfhi1(), &sc->sc_hi1);
595 err |= __put_user(mflo1(), &sc->sc_lo1);
596 err |= __put_user(mfhi2(), &sc->sc_hi2);
597 err |= __put_user(mflo2(), &sc->sc_lo2);
598 err |= __put_user(mfhi3(), &sc->sc_hi3);
599 err |= __put_user(mflo3(), &sc->sc_lo3);
600 }
555 601
556 err |= __put_user(!!used_math(), &sc->sc_used_math); 602 err |= __put_user(!!used_math(), &sc->sc_used_math);
557 603
@@ -601,7 +647,7 @@ static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
601 return (void *)((sp - frame_size) & ALMASK); 647 return (void *)((sp - frame_size) & ALMASK);
602} 648}
603 649
604static inline void setup_frame(struct k_sigaction * ka, struct pt_regs *regs, 650void setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
605 int signr, sigset_t *set) 651 int signr, sigset_t *set)
606{ 652{
607 struct sigframe *frame; 653 struct sigframe *frame;
@@ -654,9 +700,7 @@ give_sigsegv:
654 force_sigsegv(signr, current); 700 force_sigsegv(signr, current);
655} 701}
656 702
657static inline void setup_rt_frame(struct k_sigaction * ka, 703void setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info)
658 struct pt_regs *regs, int signr,
659 sigset_t *set, siginfo_t *info)
660{ 704{
661 struct rt_sigframe32 *frame; 705 struct rt_sigframe32 *frame;
662 int err = 0; 706 int err = 0;
@@ -725,9 +769,11 @@ give_sigsegv:
725 force_sigsegv(signr, current); 769 force_sigsegv(signr, current);
726} 770}
727 771
728static inline void handle_signal(unsigned long sig, siginfo_t *info, 772static inline int handle_signal(unsigned long sig, siginfo_t *info,
729 struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs) 773 struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs)
730{ 774{
775 int ret;
776
731 switch (regs->regs[0]) { 777 switch (regs->regs[0]) {
732 case ERESTART_RESTARTBLOCK: 778 case ERESTART_RESTARTBLOCK:
733 case ERESTARTNOHAND: 779 case ERESTARTNOHAND:
@@ -747,9 +793,9 @@ static inline void handle_signal(unsigned long sig, siginfo_t *info,
747 regs->regs[0] = 0; /* Don't deal with this again. */ 793 regs->regs[0] = 0; /* Don't deal with this again. */
748 794
749 if (ka->sa.sa_flags & SA_SIGINFO) 795 if (ka->sa.sa_flags & SA_SIGINFO)
750 setup_rt_frame(ka, regs, sig, oldset, info); 796 ret = current->thread.abi->setup_rt_frame(ka, regs, sig, oldset, info);
751 else 797 else
752 setup_frame(ka, regs, sig, oldset); 798 ret = current->thread.abi->setup_frame(ka, regs, sig, oldset);
753 799
754 spin_lock_irq(&current->sighand->siglock); 800 spin_lock_irq(&current->sighand->siglock);
755 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask); 801 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -757,6 +803,8 @@ static inline void handle_signal(unsigned long sig, siginfo_t *info,
757 sigaddset(&current->blocked,sig); 803 sigaddset(&current->blocked,sig);
758 recalc_sigpending(); 804 recalc_sigpending();
759 spin_unlock_irq(&current->sighand->siglock); 805 spin_unlock_irq(&current->sighand->siglock);
806
807 return ret;
760} 808}
761 809
762int do_signal32(sigset_t *oldset, struct pt_regs *regs) 810int do_signal32(sigset_t *oldset, struct pt_regs *regs)
@@ -780,10 +828,8 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
780 oldset = &current->blocked; 828 oldset = &current->blocked;
781 829
782 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 830 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
783 if (signr > 0) { 831 if (signr > 0)
784 handle_signal(signr, &info, &ka, oldset, regs); 832 return handle_signal(signr, &info, &ka, oldset, regs);
785 return 1;
786 }
787 833
788no_signal: 834no_signal:
789 /* 835 /*
@@ -819,12 +865,13 @@ asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 *act,
819 goto out; 865 goto out;
820 866
821 if (act) { 867 if (act) {
868 s32 handler;
822 int err = 0; 869 int err = 0;
823 870
824 if (!access_ok(VERIFY_READ, act, sizeof(*act))) 871 if (!access_ok(VERIFY_READ, act, sizeof(*act)))
825 return -EFAULT; 872 return -EFAULT;
826 err |= __get_user((u32)(u64)new_sa.sa.sa_handler, 873 err |= __get_user(handler, &act->sa_handler);
827 &act->sa_handler); 874 new_sa.sa.sa_handler = (void*)(s64)handler;
828 err |= __get_user(new_sa.sa.sa_flags, &act->sa_flags); 875 err |= __get_user(new_sa.sa.sa_flags, &act->sa_flags);
829 err |= get_sigset(&new_sa.sa.sa_mask, &act->sa_mask); 876 err |= get_sigset(&new_sa.sa.sa_mask, &act->sa_mask);
830 if (err) 877 if (err)
@@ -902,3 +949,30 @@ asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t *uinfo)
902 set_fs (old_fs); 949 set_fs (old_fs);
903 return ret; 950 return ret;
904} 951}
952
953asmlinkage long
954sys32_waitid(int which, compat_pid_t pid,
955 compat_siginfo_t __user *uinfo, int options,
956 struct compat_rusage __user *uru)
957{
958 siginfo_t info;
959 struct rusage ru;
960 long ret;
961 mm_segment_t old_fs = get_fs();
962
963 info.si_signo = 0;
964 set_fs (KERNEL_DS);
965 ret = sys_waitid(which, pid, (siginfo_t __user *) &info, options,
966 uru ? (struct rusage __user *) &ru : NULL);
967 set_fs (old_fs);
968
969 if (ret < 0 || info.si_signo == 0)
970 return ret;
971
972 if (uru && (ret = put_compat_rusage(&ru, uru)))
973 return ret;
974
975 BUG_ON(info.si_code & __SI_MASK);
976 info.si_code |= __SI_CHLD;
977 return copy_siginfo_to_user32(uinfo, &info);
978}