aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/signal_64.c
diff options
context:
space:
mode:
authorMichael Neuling <mikey@neuling.org>2008-06-25 00:07:18 -0400
committerPaul Mackerras <paulus@samba.org>2008-06-30 21:28:46 -0400
commitc6e6771b87d4e339d27f1383c8a808ae9b4ee5b8 (patch)
tree1900b7350ec685c3a31f2233fd88a57e34725b5c /arch/powerpc/kernel/signal_64.c
parent6f3d8e6947ec98e358514fc0f7b2e37fe88a21bb (diff)
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 <mikey@neuling.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/signal_64.c')
-rw-r--r--arch/powerpc/kernel/signal_64.c32
1 files changed, 29 insertions, 3 deletions
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,
89#endif 89#endif
90 unsigned long msr = regs->msr; 90 unsigned long msr = regs->msr;
91 long err = 0; 91 long err = 0;
92#ifdef CONFIG_VSX
93 double buf[FP_REGS_SIZE];
94 int i;
95#endif
92 96
93 flush_fp_to_thread(current); 97 flush_fp_to_thread(current);
94 98
@@ -112,11 +116,21 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
112#else /* CONFIG_ALTIVEC */ 116#else /* CONFIG_ALTIVEC */
113 err |= __put_user(0, &sc->v_regs); 117 err |= __put_user(0, &sc->v_regs);
114#endif /* CONFIG_ALTIVEC */ 118#endif /* CONFIG_ALTIVEC */
119 flush_fp_to_thread(current);
120#ifdef CONFIG_VSX
121 /* Copy FP to local buffer then write that out */
122 for (i = 0; i < 32 ; i++)
123 buf[i] = current->thread.TS_FPR(i);
124 memcpy(&buf[i], &current->thread.fpscr, sizeof(double));
125 err |= __copy_to_user(&sc->fp_regs, buf, FP_REGS_SIZE);
126#else /* CONFIG_VSX */
127 /* copy fpr regs and fpscr */
128 err |= __copy_to_user(&sc->fp_regs, &current->thread.fpr, FP_REGS_SIZE);
129#endif /* CONFIG_VSX */
115 err |= __put_user(&sc->gp_regs, &sc->regs); 130 err |= __put_user(&sc->gp_regs, &sc->regs);
116 WARN_ON(!FULL_REGS(regs)); 131 WARN_ON(!FULL_REGS(regs));
117 err |= __copy_to_user(&sc->gp_regs, regs, GP_REGS_SIZE); 132 err |= __copy_to_user(&sc->gp_regs, regs, GP_REGS_SIZE);
118 err |= __put_user(msr, &sc->gp_regs[PT_MSR]); 133 err |= __put_user(msr, &sc->gp_regs[PT_MSR]);
119 err |= __copy_to_user(&sc->fp_regs, &current->thread.fpr, FP_REGS_SIZE);
120 err |= __put_user(signr, &sc->signal); 134 err |= __put_user(signr, &sc->signal);
121 err |= __put_user(handler, &sc->handler); 135 err |= __put_user(handler, &sc->handler);
122 if (set != NULL) 136 if (set != NULL)
@@ -135,6 +149,9 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
135#ifdef CONFIG_ALTIVEC 149#ifdef CONFIG_ALTIVEC
136 elf_vrreg_t __user *v_regs; 150 elf_vrreg_t __user *v_regs;
137#endif 151#endif
152#ifdef CONFIG_VSX
153 double buf[FP_REGS_SIZE];
154#endif
138 unsigned long err = 0; 155 unsigned long err = 0;
139 unsigned long save_r13 = 0; 156 unsigned long save_r13 = 0;
140 elf_greg_t *gregs = (elf_greg_t *)regs; 157 elf_greg_t *gregs = (elf_greg_t *)regs;
@@ -182,8 +199,6 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
182 */ 199 */
183 regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1 | MSR_VEC); 200 regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1 | MSR_VEC);
184 201
185 err |= __copy_from_user(&current->thread.fpr, &sc->fp_regs, FP_REGS_SIZE);
186
187#ifdef CONFIG_ALTIVEC 202#ifdef CONFIG_ALTIVEC
188 err |= __get_user(v_regs, &sc->v_regs); 203 err |= __get_user(v_regs, &sc->v_regs);
189 if (err) 204 if (err)
@@ -202,7 +217,18 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
202 else 217 else
203 current->thread.vrsave = 0; 218 current->thread.vrsave = 0;
204#endif /* CONFIG_ALTIVEC */ 219#endif /* CONFIG_ALTIVEC */
220#ifdef CONFIG_VSX
221 /* restore floating point */
222 err |= __copy_from_user(buf, &sc->fp_regs, FP_REGS_SIZE);
223 if (err)
224 return err;
225 for (i = 0; i < 32 ; i++)
226 current->thread.TS_FPR(i) = buf[i];
227 memcpy(&current->thread.fpscr, &buf[i], sizeof(double));
205 228
229#else
230 err |= __copy_from_user(&current->thread.fpr, &sc->fp_regs, FP_REGS_SIZE);
231#endif
206 return err; 232 return err;
207} 233}
208 234