#include <linux/errno.h>
#include <linux/elf.h>
#include <linux/compat.h>
+#include <linux/ptrace.h>
#include <asm/ppc32.h>
#include <asm/uaccess.h>
#include <asm/ppcdebug.h>
*
*/
struct rt_sigframe32 {
- struct compat_siginfo info;
+ compat_siginfo_t info;
struct ucontext32 uc;
/*
* Programs using the rs6000/xcoff abi can save up to 19 gp
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
sizeof(sr->mc_vregs)))
return 1;
} else if (current->thread.used_vr)
- memset(¤t->thread.vr, 0, ELF_NVRREG32 * sizeof(vector128));
+ memset(current->thread.vr, 0, ELF_NVRREG32 * sizeof(vector128));
/* Always get VRSAVE back */
if (__get_user(current->thread.vrsave, (u32 __user *)&sr->mc_vregs[32]))
return 1;
#endif /* CONFIG_ALTIVEC */
+#ifndef CONFIG_SMP
+ preempt_disable();
+ if (last_task_used_math == current)
+ last_task_used_math = NULL;
+ if (last_task_used_altivec == current)
+ last_task_used_altivec = NULL;
+ preempt_enable();
+#endif
return 0;
}
schedule();
if (do_signal32(&saveset, regs))
/*
- * If a signal handler needs to be called,
- * do_signal32() has set R3 to the signal number (the
- * first argument of the signal handler), so don't
- * overwrite that with EINTR !
- * In the other cases, do_signal32() doesn't touch
- * R3, so it's still set to -EINTR (see above).
+ * Returning 0 means we return to userspace via
+ * ret_from_except and thus restore all user
+ * registers from *regs. This is what we need
+ * to do when a signal has been delivered.
*/
- return regs->gpr[3];
+ return 0;
}
}
* sigpending sys32_rt_sigpending
* sigprocmask sys32_rt_sigprocmask
* sigreturn sys32_rt_sigreturn
- * sigtimedwait sys32_rt_sigtimedwait
* sigqueueinfo sys32_rt_sigqueueinfo
* sigsuspend sys32_rt_sigsuspend
*
}
-static long copy_siginfo_to_user32(compat_siginfo_t __user *d, siginfo_t *s)
+int copy_siginfo_to_user32(struct compat_siginfo __user *d, siginfo_t *s)
{
- long err;
+ int err;
if (!access_ok (VERIFY_WRITE, d, sizeof(*d)))
return -EFAULT;
&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);
return err;
}
-long sys32_rt_sigtimedwait(compat_sigset_t __user *uthese, compat_siginfo_t __user *uinfo,
- struct compat_timespec __user *uts, compat_size_t sigsetsize)
-{
- sigset_t s;
- compat_sigset_t s32;
- struct timespec t;
- int ret;
- mm_segment_t old_fs = get_fs();
- siginfo_t info;
-
- if (copy_from_user(&s32, uthese, sizeof(compat_sigset_t)))
- return -EFAULT;
- sigset_from_compat(&s, &s32);
- if (uts && get_compat_timespec(&t, uts))
- return -EFAULT;
- set_fs(KERNEL_DS);
- /* The __user pointer casts are valid because of the set_fs() */
- ret = sys_rt_sigtimedwait((sigset_t __user *) &s,
- uinfo ? (siginfo_t __user *) &info : NULL,
- uts ? (struct timespec __user *) &t : NULL,
- sigsetsize);
- set_fs(old_fs);
- if (ret >= 0 && uinfo) {
- if (copy_siginfo_to_user32(uinfo, &info))
- return -EFAULT;
- }
- return ret;
-}
-
/*
* Note: it is necessary to treat pid and sig as unsigned ints, with the
* corresponding cast to a signed int to insure that the proper conversion
schedule();
if (do_signal32(&saveset, regs))
/*
- * If a signal handler needs to be called,
- * do_signal32() has set R3 to the signal number (the
- * first argument of the signal handler), so don't
- * overwrite that with EINTR !
- * In the other cases, do_signal32() doesn't touch
- * R3, so it's still set to -EINTR (see above).
+ * Returning 0 means we return to userspace via
+ * ret_from_except and thus restore all user
+ * registers from *regs. This is what we need
+ * to do when a signal has been delivered.
*/
- return regs->gpr[3];
+ return 0;
}
}
* Set up a signal frame for a "real-time" signal handler
* (one which gets siginfo).
*/
-static void handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
- siginfo_t *info, sigset_t *oldset,
- struct pt_regs * regs, unsigned long newsp)
+static int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
+ siginfo_t *info, sigset_t *oldset,
+ struct pt_regs * regs, unsigned long newsp)
{
struct rt_sigframe32 __user *rt_sf;
struct mcontext32 __user *frame;
regs->trap = 0;
regs->result = 0;
- return;
+ if (test_thread_flag(TIF_SINGLESTEP))
+ ptrace_notify(SIGTRAP);
+
+ return 1;
badframe:
#if DEBUG_SIG
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);
+ return 0;
}
static long do_setcontext32(struct ucontext32 __user *ucp, struct pt_regs *regs, int sig)
/*
* OK, we're invoking a handler
*/
-static void handle_signal32(unsigned long sig, struct k_sigaction *ka,
+static int handle_signal32(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset,
struct pt_regs * regs, unsigned long newsp)
{
regs->trap = 0;
regs->result = 0;
- return;
+ if (test_thread_flag(TIF_SINGLESTEP))
+ ptrace_notify(SIGTRAP);
+
+ return 1;
badframe:
#if DEBUG_SIG
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);
+ return 0;
}
/*
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 = ¤t->blocked;
newsp = frame = 0;
- signr = get_signal_to_deliver(&info, regs, NULL);
-
- ka = (signr == 0)? NULL: ¤t->sighand->action[signr-1];
+ signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (TRAP(regs) == 0x0C00 /* System Call! */
&& regs->ccr & 0x10000000 /* error signalled */
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;
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
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)
+ ret = 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;
+ ret = handle_signal32(signr, &ka, &info, oldset, regs, newsp);
- if (!(ka->sa.sa_flags & SA_NODEFER)) {
+ if (ret && !(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, signr);
recalc_sigpending();
spin_unlock_irq(¤t->sighand->siglock);
}
- return 1;
+ return ret;
}