X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fppc64%2Fkernel%2Fsignal.c;h=ce616280b7bd85cb107be2e337fe7b2e59c8c3ed;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=7b75311c1c2f9e58e2a091702c22f4c39fbcf605;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/arch/ppc64/kernel/signal.c b/arch/ppc64/kernel/signal.c index 7b75311c1..ce616280b 100644 --- a/arch/ppc64/kernel/signal.c +++ b/arch/ppc64/kernel/signal.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -73,7 +72,7 @@ struct rt_sigframe { /* * Atomically swap in the new signal mask, and wait for a signal. */ -long sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, int p3, int p4, +long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, int p3, int p4, int p6, int p7, struct pt_regs *regs) { sigset_t saveset, newset; @@ -103,7 +102,7 @@ long sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, int p3, int p4, } } -long sys_sigaltstack(const stack_t *uss, stack_t *uoss, unsigned long r5, +long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r5, unsigned long r6, unsigned long r7, unsigned long r8, struct pt_regs *regs) { @@ -115,7 +114,7 @@ long sys_sigaltstack(const stack_t *uss, stack_t *uoss, unsigned long r5, * Set up the sigcontext for the signal frame. */ -static long setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, +static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, int signr, sigset_t *set, unsigned long handler) { /* When CONFIG_ALTIVEC is set, we _always_ setup v_regs even if the @@ -127,12 +126,11 @@ static long setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, * v_regs pointer or not */ #ifdef CONFIG_ALTIVEC - elf_vrreg_t *v_regs = (elf_vrreg_t *)(((unsigned long)sc->vmx_reserve) & ~0xful); + elf_vrreg_t __user *v_regs = (elf_vrreg_t __user *)(((unsigned long)sc->vmx_reserve + 15) & ~0xful); #endif long err = 0; - if (regs->msr & MSR_FP) - giveup_fpu(current); + flush_fp_to_thread(current); /* Make sure signal doesn't get spurrious FP exceptions */ current->thread.fpscr = 0; @@ -141,9 +139,8 @@ static long setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, err |= __put_user(v_regs, &sc->v_regs); /* save altivec registers */ - if (current->thread.used_vr) { - if (regs->msr & MSR_VEC) - giveup_altivec(current); + if (current->thread.used_vr) { + flush_altivec_to_thread(current); /* Copy 33 vec registers (vr0..31 and vscr) to the stack */ err |= __copy_to_user(v_regs, current->thread.vr, 33 * sizeof(vector128)); /* set MSR_VEC in the MSR value in the frame to indicate that sc->v_reg) @@ -154,7 +151,7 @@ static long setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, /* We always copy to/from vrsave, it's 0 if we don't have or don't * use altivec. */ - err |= __put_user(current->thread.vrsave, (u32 *)&v_regs[33]); + err |= __put_user(current->thread.vrsave, (u32 __user *)&v_regs[33]); #else /* CONFIG_ALTIVEC */ err |= __put_user(0, &sc->v_regs); #endif /* CONFIG_ALTIVEC */ @@ -174,13 +171,13 @@ static long setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, */ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, - struct sigcontext *sc) + struct sigcontext __user *sc) { #ifdef CONFIG_ALTIVEC - elf_vrreg_t *v_regs; + elf_vrreg_t __user *v_regs; #endif unsigned long err = 0; - unsigned long save_r13; + unsigned long save_r13 = 0; elf_greg_t *gregs = (elf_greg_t *)regs; int i; @@ -216,7 +213,7 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, memset(¤t->thread.vr, 0, 33); /* Always get VRSAVE back */ if (v_regs != 0) - err |= __get_user(current->thread.vrsave, (u32 *)&v_regs[33]); + err |= __get_user(current->thread.vrsave, (u32 __user *)&v_regs[33]); else current->thread.vrsave = 0; #endif /* CONFIG_ALTIVEC */ @@ -230,7 +227,7 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, /* * Allocate space for the signal frame */ -static inline void * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, +static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) { unsigned long newsp; @@ -243,13 +240,13 @@ static inline void * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, newsp = (current->sas_ss_sp + current->sas_ss_size); } - return (void *)((newsp - frame_size) & -8ul); + return (void __user *)((newsp - frame_size) & -8ul); } /* * Setup the trampoline code on the stack */ -static long setup_trampoline(unsigned int syscall, unsigned int *tramp) +static long setup_trampoline(unsigned int syscall, unsigned int __user *tramp) { int i; long err = 0; @@ -311,8 +308,8 @@ int sys_swapcontext(struct ucontext __user *old_ctx, if (new_ctx == NULL) return 0; if (verify_area(VERIFY_READ, new_ctx, sizeof(*new_ctx)) - || __get_user(tmp, (u8 *) new_ctx) - || __get_user(tmp, (u8 *) (new_ctx + 1) - 1)) + || __get_user(tmp, (u8 __user *) new_ctx) + || __get_user(tmp, (u8 __user *) (new_ctx + 1) - 1)) return -EFAULT; /* @@ -346,7 +343,7 @@ int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, unsigned long r8, struct pt_regs *regs) { - struct ucontext *uc = (struct ucontext *)regs->gpr[1]; + struct ucontext __user *uc = (struct ucontext __user *)regs->gpr[1]; sigset_t set; /* Always make any pending restarted system calls return -EINTR */ @@ -373,7 +370,8 @@ badframe: printk("badframe in sys_rt_sigreturn, regs=%p uc=%p &uc->uc_mcontext=%p\n", regs, uc, &uc->uc_mcontext); #endif - do_exit(SIGSEGV); + force_sig(SIGSEGV, current); + return 0; } static void setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, @@ -384,8 +382,8 @@ static void setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, * descriptor is the entry address of signal and the second * entry is the TOC value we need to use. */ - func_descr_t *funct_desc_ptr; - struct rt_sigframe *frame; + func_descr_t __user *funct_desc_ptr; + struct rt_sigframe __user *frame; unsigned long newsp = 0; long err = 0; @@ -418,11 +416,11 @@ static void setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, if (err) goto badframe; - funct_desc_ptr = (func_descr_t *) ka->sa.sa_handler; + funct_desc_ptr = (func_descr_t __user *) ka->sa.sa_handler; /* Allocate a dummy caller frame for the signal handler. */ newsp = (unsigned long)frame - __SIGNAL_FRAMESIZE; - err |= put_user(0, (unsigned long *)newsp); + err |= put_user(0, (unsigned long __user *)newsp); /* Set up "regs" so we "return" to the signal handler. */ err |= get_user(regs->nip, &funct_desc_ptr->entry); @@ -432,8 +430,8 @@ static void setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, regs->gpr[3] = signr; regs->result = 0; if (ka->sa.sa_flags & SA_SIGINFO) { - err |= get_user(regs->gpr[4], (unsigned long *)&frame->pinfo); - err |= get_user(regs->gpr[5], (unsigned long *)&frame->puc); + err |= get_user(regs->gpr[4], (unsigned long __user *)&frame->pinfo); + err |= get_user(regs->gpr[5], (unsigned long __user *)&frame->puc); regs->gpr[6] = (unsigned long) frame; } else { regs->gpr[4] = (unsigned long)&frame->uc.uc_mcontext; @@ -448,7 +446,7 @@ badframe: printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); #endif - do_exit(SIGSEGV); + force_sigsegv(signr, current); } @@ -461,17 +459,13 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka, /* Set up Signal Frame */ setup_rt_frame(sig, ka, info, oldset, regs); - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; - if (!(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); sigaddset(¤t->blocked,sig); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); } - return; } static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) @@ -514,6 +508,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) { siginfo_t info; int signr; + struct k_sigaction ka; /* * If the current thread is 32 bit - invoke the @@ -525,18 +520,16 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) if (!oldset) oldset = ¤t->blocked; - signr = get_signal_to_deliver(&info, regs, NULL); + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { - struct k_sigaction *ka = ¤t->sighand->action[signr-1]; - /* Whee! Actually deliver the signal. */ - if (regs->trap == 0x0C00) - syscall_restart(regs, ka); - handle_signal(signr, ka, &info, oldset, regs); + if (TRAP(regs) == 0x0C00) + syscall_restart(regs, &ka); + handle_signal(signr, &ka, &info, oldset, regs); return 1; } - if (regs->trap == 0x0C00) { /* System Call! */ + if (TRAP(regs) == 0x0C00) { /* System Call! */ if ((int)regs->result == -ERESTARTNOHAND || (int)regs->result == -ERESTARTSYS || (int)regs->result == -ERESTARTNOINTR) {