vserver 1.9.3
[linux-2.6.git] / arch / ppc64 / kernel / signal32.c
index c8f6294..79f7b84 100644 (file)
@@ -130,11 +130,10 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext32 __user *frame,
 {
        elf_greg_t64 *gregs = (elf_greg_t64 *)regs;
        int i, err = 0;
-       
-       /* Make sure floating point registers are stored in regs */ 
-       if (regs->msr & MSR_FP)
-               giveup_fpu(current);
-       
+
+       /* Make sure floating point registers are stored in regs */
+       flush_fp_to_thread(current);
+
        /* save general and floating-point registers */
        for (i = 0; i <= PT_RESULT; i ++)
                err |= __put_user((unsigned int)gregs[i], &frame->mc_gregs[i]);
@@ -148,8 +147,7 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext32 __user *frame,
 #ifdef CONFIG_ALTIVEC
        /* save altivec registers */
        if (current->thread.used_vr) {
-               if (regs->msr & MSR_VEC)
-                       giveup_altivec(current);
+               flush_altivec_to_thread(current);
                if (__copy_to_user(&frame->mc_vregs, current->thread.vr,
                                   ELF_NVRREG32 * sizeof(vector128)))
                        return 1;
@@ -191,7 +189,7 @@ static long restore_user_regs(struct pt_regs *regs,
        elf_greg_t64 *gregs = (elf_greg_t64 *)regs;
        int i;
        long err = 0;
-       unsigned int save_r2;
+       unsigned int save_r2 = 0;
 #ifdef CONFIG_ALTIVEC
        unsigned long msr;
 #endif
@@ -300,12 +298,15 @@ long sys32_sigaction(int sig, struct old_sigaction32 __user *act,
 
        if (act) {
                compat_old_sigset_t mask;
+               compat_uptr_t handler, restorer;
 
-               if (get_user((long)new_ka.sa.sa_handler, &act->sa_handler) ||
-                   __get_user((long)new_ka.sa.sa_restorer, &act->sa_restorer) ||
+               if (get_user(handler, &act->sa_handler) ||
+                   __get_user(restorer, &act->sa_restorer) ||
                    __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
                    __get_user(mask, &act->sa_mask))
                        return -EFAULT;
+               new_ka.sa.sa_handler = compat_ptr(handler);
+               new_ka.sa.sa_restorer = compat_ptr(restorer);
                siginitset(&new_ka.sa.sa_mask, mask);
        }
 
@@ -356,7 +357,10 @@ long sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
                return -EINVAL;
 
        if (act) {
-               ret = get_user((long)new_ka.sa.sa_handler, &act->sa_handler);
+               compat_uptr_t handler;
+
+               ret = get_user(handler, &act->sa_handler);
+               new_ka.sa.sa_handler = compat_ptr(handler);
                ret |= __copy_from_user(&set32, &act->sa_mask,
                                        sizeof(compat_sigset_t));
                sigset_from_compat(&new_ka.sa.sa_mask, &set32);
@@ -468,10 +472,14 @@ static long copy_siginfo_to_user32(compat_siginfo_t __user *d, siginfo_t *s)
                                  &d->si_addr);
                break;
        case __SI_POLL >> 16:
-       case __SI_TIMER >> 16:
                err |= __put_user(s->si_band, &d->si_band);
                err |= __put_user(s->si_fd, &d->si_fd);
                break;
+       case __SI_TIMER >> 16:
+               err |= __put_user(s->si_tid, &d->si_tid);
+               err |= __put_user(s->si_overrun, &d->si_overrun);
+               err |= __put_user(s->si_int, &d->si_int);
+               break;
        case __SI_RT >> 16: /* This is not generated by the kernel as of now.  */
        case __SI_MESGQ >> 16:
                err |= __put_user(s->si_int, &d->si_int);
@@ -598,6 +606,7 @@ int sys32_sigaltstack(u32 __new, u32 __old, int r5,
        int ret;
        mm_segment_t old_fs;
        unsigned long sp;
+       compat_uptr_t ss_sp;
 
        /*
         * set sp to the user stack on entry to the system call
@@ -606,11 +615,13 @@ int sys32_sigaltstack(u32 __new, u32 __old, int r5,
        sp = regs->gpr[1];
 
        /* Put new stack info in local 64 bit stack struct */
-       if (newstack &&
-               (get_user((long)uss.ss_sp, &newstack->ss_sp) ||
-                __get_user(uss.ss_flags, &newstack->ss_flags) ||
-                __get_user(uss.ss_size, &newstack->ss_size)))
-               return -EFAULT; 
+       if (newstack) {
+               if (get_user(ss_sp, &newstack->ss_sp) ||
+                   __get_user(uss.ss_flags, &newstack->ss_flags) ||
+                   __get_user(uss.ss_size, &newstack->ss_size))
+                       return -EFAULT;
+               uss.ss_sp = compat_ptr(ss_sp);
+       }
 
        old_fs = get_fs();
        set_fs(KERNEL_DS);
@@ -692,9 +703,7 @@ badframe:
        printk("badframe in handle_rt_signal, regs=%p frame=%p newsp=%lx\n",
               regs, frame, newsp);
 #endif
-       if (sig == SIGSEGV)
-               ka->sa.sa_handler = SIG_DFL;
-       force_sig(SIGSEGV, current);
+       force_sigsegv(sig, current);
 }
 
 static long do_setcontext32(struct ucontext32 __user *ucp, struct pt_regs *regs, int sig)
@@ -857,9 +866,7 @@ badframe:
        printk("badframe in handle_signal, regs=%p frame=%x newsp=%x\n",
               regs, frame, *newspp);
 #endif
-       if (sig == SIGSEGV)
-               ka->sa.sa_handler = SIG_DFL;
-       force_sig(SIGSEGV, current);
+       force_sigsegv(sig, current);
 }
 
 /*
@@ -921,20 +928,18 @@ badframe:
 int do_signal32(sigset_t *oldset, struct pt_regs *regs)
 {
        siginfo_t info;
-       struct k_sigaction *ka;
        unsigned int frame, newsp;
        int signr, ret;
+       struct k_sigaction ka;
 
        if (!oldset)
                oldset = &current->blocked;
 
        newsp = frame = 0;
 
-       signr = get_signal_to_deliver(&info, regs, NULL);
-
-       ka = (signr == 0)? NULL: &current->sighand->action[signr-1];
+       signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 
-       if (regs->trap == 0x0C00                /* System Call! */
+       if (TRAP(regs) == 0x0C00                /* System Call! */
            && regs->ccr & 0x10000000           /* error signalled */
            && ((ret = regs->gpr[3]) == ERESTARTSYS
                || ret == ERESTARTNOHAND || ret == ERESTARTNOINTR
@@ -943,7 +948,7 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
                if (signr > 0
                    && (ret == ERESTARTNOHAND || ret == ERESTART_RESTARTBLOCK
                        || (ret == ERESTARTSYS
-                           && !(ka->sa.sa_flags & SA_RESTART)))) {
+                           && !(ka.sa.sa_flags & SA_RESTART)))) {
                        /* make the system call return an EINTR error */
                        regs->result = -EINTR;
                        regs->gpr[3] = EINTR;
@@ -962,7 +967,7 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
        if (signr == 0)
                return 0;               /* no signals delivered */
 
-       if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size
+       if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size
            && (!on_sig_stack(regs->gpr[1])))
                newsp = (current->sas_ss_sp + current->sas_ss_size);
        else
@@ -970,17 +975,15 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
        newsp &= ~0xfUL;
 
        /* Whee!  Actually deliver the signal.  */
-       if (ka->sa.sa_flags & SA_SIGINFO)
-               handle_rt_signal32(signr, ka, &info, oldset, regs, newsp);
+       if (ka.sa.sa_flags & SA_SIGINFO)
+               handle_rt_signal32(signr, &ka, &info, oldset, regs, newsp);
        else
-               handle_signal32(signr, ka, &info, oldset, regs, newsp);
-
-       if (ka->sa.sa_flags & SA_ONESHOT)
-               ka->sa.sa_handler = SIG_DFL;
+               handle_signal32(signr, &ka, &info, oldset, regs, newsp);
 
-       if (!(ka->sa.sa_flags & SA_NODEFER)) {
+       if (!(ka.sa.sa_flags & SA_NODEFER)) {
                spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+               sigorsets(&current->blocked, &current->blocked,
+                         &ka.sa.sa_mask);
                sigaddset(&current->blocked, signr);
                recalc_sigpending();
                spin_unlock_irq(&current->sighand->siglock);