From c6e6771b87d4e339d27f1383c8a808ae9b4ee5b8 Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Wed, 25 Jun 2008 14:07:18 +1000 Subject: powerpc: Introduce VSX thread_struct and CONFIG_VSX The layout of the new VSR registers and how they overlap on top of the legacy FPR and VR registers is: VSR doubleword 0 VSR doubleword 1 ---------------------------------------------------------------- VSR[0] | FPR[0] | | ---------------------------------------------------------------- VSR[1] | FPR[1] | | ---------------------------------------------------------------- | ... | | | ... | | ---------------------------------------------------------------- VSR[30] | FPR[30] | | ---------------------------------------------------------------- VSR[31] | FPR[31] | | ---------------------------------------------------------------- VSR[32] | VR[0] | ---------------------------------------------------------------- VSR[33] | VR[1] | ---------------------------------------------------------------- | ... | | ... | ---------------------------------------------------------------- VSR[62] | VR[30] | ---------------------------------------------------------------- VSR[63] | VR[31] | ---------------------------------------------------------------- VSX has 64 128bit registers. The first 32 regs overlap with the FP registers and hence extend them with and additional 64 bits. The second 32 regs overlap with the VMX registers. This commit introduces the thread_struct changes required to reflect this register layout. Ptrace and signals code is updated so that the floating point registers are correctly accessed from the thread_struct when CONFIG_VSX is enabled. Signed-off-by: Michael Neuling Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/signal_64.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) (limited to 'arch/powerpc/kernel/signal_64.c') diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index da7c058e3731..a587b33cd6b9 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -89,6 +89,10 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, #endif unsigned long msr = regs->msr; long err = 0; +#ifdef CONFIG_VSX + double buf[FP_REGS_SIZE]; + int i; +#endif flush_fp_to_thread(current); @@ -112,11 +116,21 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, #else /* CONFIG_ALTIVEC */ err |= __put_user(0, &sc->v_regs); #endif /* CONFIG_ALTIVEC */ + flush_fp_to_thread(current); +#ifdef CONFIG_VSX + /* Copy FP to local buffer then write that out */ + for (i = 0; i < 32 ; i++) + buf[i] = current->thread.TS_FPR(i); + memcpy(&buf[i], ¤t->thread.fpscr, sizeof(double)); + err |= __copy_to_user(&sc->fp_regs, buf, FP_REGS_SIZE); +#else /* CONFIG_VSX */ + /* copy fpr regs and fpscr */ + err |= __copy_to_user(&sc->fp_regs, ¤t->thread.fpr, FP_REGS_SIZE); +#endif /* CONFIG_VSX */ err |= __put_user(&sc->gp_regs, &sc->regs); WARN_ON(!FULL_REGS(regs)); err |= __copy_to_user(&sc->gp_regs, regs, GP_REGS_SIZE); err |= __put_user(msr, &sc->gp_regs[PT_MSR]); - err |= __copy_to_user(&sc->fp_regs, ¤t->thread.fpr, FP_REGS_SIZE); err |= __put_user(signr, &sc->signal); err |= __put_user(handler, &sc->handler); if (set != NULL) @@ -134,6 +148,9 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, { #ifdef CONFIG_ALTIVEC elf_vrreg_t __user *v_regs; +#endif +#ifdef CONFIG_VSX + double buf[FP_REGS_SIZE]; #endif unsigned long err = 0; unsigned long save_r13 = 0; @@ -182,8 +199,6 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, */ regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1 | MSR_VEC); - err |= __copy_from_user(¤t->thread.fpr, &sc->fp_regs, FP_REGS_SIZE); - #ifdef CONFIG_ALTIVEC err |= __get_user(v_regs, &sc->v_regs); if (err) @@ -202,7 +217,18 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, else current->thread.vrsave = 0; #endif /* CONFIG_ALTIVEC */ +#ifdef CONFIG_VSX + /* restore floating point */ + err |= __copy_from_user(buf, &sc->fp_regs, FP_REGS_SIZE); + if (err) + return err; + for (i = 0; i < 32 ; i++) + current->thread.TS_FPR(i) = buf[i]; + memcpy(¤t->thread.fpscr, &buf[i], sizeof(double)); +#else + err |= __copy_from_user(¤t->thread.fpr, &sc->fp_regs, FP_REGS_SIZE); +#endif return err; } -- cgit v1.2.2