aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/signal_64.c
diff options
context:
space:
mode:
authorMichael Neuling <mikey@neuling.org>2008-07-02 00:06:37 -0400
committerPaul Mackerras <paulus@samba.org>2008-07-03 02:58:11 -0400
commit6a274c08f2f4dfac7167bbd849621f3a2b55d424 (patch)
tree1bad45a11c1e436ffbcb84107783da0e423925f9 /arch/powerpc/kernel/signal_64.c
parent2d1b2027626d5151fff8ef7c06ca8e7876a1a510 (diff)
powerpc: Clean up copy_to/from_user for vsx and fpr
This merges and cleans up some of the ugly copy/to from user code which is required for the new fpr and vsx layout in the thread_struct. Also fixes some hard coded buffer sizes and removes a redundant fpr_flush_to_thread. 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.c43
1 files changed, 11 insertions, 32 deletions
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 8214e57aab67..93ebfb6944b6 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -89,10 +89,6 @@ 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
96 92
97 flush_fp_to_thread(current); 93 flush_fp_to_thread(current);
98 94
@@ -117,12 +113,9 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
117 err |= __put_user(0, &sc->v_regs); 113 err |= __put_user(0, &sc->v_regs);
118#endif /* CONFIG_ALTIVEC */ 114#endif /* CONFIG_ALTIVEC */
119 flush_fp_to_thread(current); 115 flush_fp_to_thread(current);
116 /* copy fpr regs and fpscr */
117 err |= copy_fpr_to_user(&sc->fp_regs, current);
120#ifdef CONFIG_VSX 118#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 /* 119 /*
127 * Copy VSX low doubleword to local buffer for formatting, 120 * Copy VSX low doubleword to local buffer for formatting,
128 * then out to userspace. Update v_regs to point after the 121 * then out to userspace. Update v_regs to point after the
@@ -131,17 +124,12 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
131 if (current->thread.used_vsr) { 124 if (current->thread.used_vsr) {
132 flush_vsx_to_thread(current); 125 flush_vsx_to_thread(current);
133 v_regs += ELF_NVRREG; 126 v_regs += ELF_NVRREG;
134 for (i = 0; i < 32 ; i++) 127 err |= copy_vsx_to_user(v_regs, current);
135 buf[i] = current->thread.fpr[i][TS_VSRLOWOFFSET];
136 err |= __copy_to_user(v_regs, buf, 32 * sizeof(double));
137 /* set MSR_VSX in the MSR value in the frame to 128 /* set MSR_VSX in the MSR value in the frame to
138 * indicate that sc->vs_reg) contains valid data. 129 * indicate that sc->vs_reg) contains valid data.
139 */ 130 */
140 msr |= MSR_VSX; 131 msr |= MSR_VSX;
141 } 132 }
142#else /* CONFIG_VSX */
143 /* copy fpr regs and fpscr */
144 err |= __copy_to_user(&sc->fp_regs, &current->thread.fpr, FP_REGS_SIZE);
145#endif /* CONFIG_VSX */ 133#endif /* CONFIG_VSX */
146 err |= __put_user(&sc->gp_regs, &sc->regs); 134 err |= __put_user(&sc->gp_regs, &sc->regs);
147 WARN_ON(!FULL_REGS(regs)); 135 WARN_ON(!FULL_REGS(regs));
@@ -165,13 +153,12 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
165#ifdef CONFIG_ALTIVEC 153#ifdef CONFIG_ALTIVEC
166 elf_vrreg_t __user *v_regs; 154 elf_vrreg_t __user *v_regs;
167#endif 155#endif
168#ifdef CONFIG_VSX
169 double buf[FP_REGS_SIZE];
170 int i;
171#endif
172 unsigned long err = 0; 156 unsigned long err = 0;
173 unsigned long save_r13 = 0; 157 unsigned long save_r13 = 0;
174 unsigned long msr; 158 unsigned long msr;
159#ifdef CONFIG_VSX
160 int i;
161#endif
175 162
176 /* If this is not a signal return, we preserve the TLS in r13 */ 163 /* If this is not a signal return, we preserve the TLS in r13 */
177 if (!sig) 164 if (!sig)
@@ -234,15 +221,9 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
234 else 221 else
235 current->thread.vrsave = 0; 222 current->thread.vrsave = 0;
236#endif /* CONFIG_ALTIVEC */ 223#endif /* CONFIG_ALTIVEC */
237#ifdef CONFIG_VSX
238 /* restore floating point */ 224 /* restore floating point */
239 err |= __copy_from_user(buf, &sc->fp_regs, FP_REGS_SIZE); 225 err |= copy_fpr_from_user(current, &sc->fp_regs);
240 if (err) 226#ifdef CONFIG_VSX
241 return err;
242 for (i = 0; i < 32 ; i++)
243 current->thread.TS_FPR(i) = buf[i];
244 memcpy(&current->thread.fpscr, &buf[i], sizeof(double));
245
246 /* 227 /*
247 * Get additional VSX data. Update v_regs to point after the 228 * Get additional VSX data. Update v_regs to point after the
248 * VMX data. Copy VSX low doubleword from userspace to local 229 * VMX data. Copy VSX low doubleword from userspace to local
@@ -250,14 +231,12 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
250 */ 231 */
251 v_regs += ELF_NVRREG; 232 v_regs += ELF_NVRREG;
252 if ((msr & MSR_VSX) != 0) 233 if ((msr & MSR_VSX) != 0)
253 err |= __copy_from_user(buf, v_regs, 32 * sizeof(double)); 234 err |= copy_vsx_from_user(current, v_regs);
254 else 235 else
255 memset(buf, 0, 32 * sizeof(double)); 236 for (i = 0; i < 32 ; i++)
237 current->thread.fpr[i][TS_VSRLOWOFFSET] = 0;
256 238
257 for (i = 0; i < 32 ; i++)
258 current->thread.fpr[i][TS_VSRLOWOFFSET] = buf[i];
259#else 239#else
260 err |= __copy_from_user(&current->thread.fpr, &sc->fp_regs, FP_REGS_SIZE);
261#endif 240#endif
262 return err; 241 return err;
263} 242}