aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/process.c
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2013-10-15 10:08:34 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2013-10-24 11:17:11 -0400
commit4725c86055f5bbdcdfe47199c0715881893a2c79 (patch)
treee201bd8d8a11e58117e9ecf360f3fab43c6267e9 /arch/s390/kernel/process.c
parent01a7cfa24afd8e18ce691d3c2f1e1f093cf3a900 (diff)
s390: fix save and restore of the floating-point-control register
The FPC_VALID_MASK has been used to check the validity of the value to be loaded into the floating-point-control register. With the introduction of the floating-point extension facility and the decimal-floating-point additional bits have been defined which need to be checked in a non straight forward way. So far these bits have been ignored which can cause an incorrect results for decimal- floating-point operations, e.g. an incorrect rounding mode to be set after signal return. The static check with the FPC_VALID_MASK is replaced with a trial load of the floating-point-control value, see test_fp_ctl. In addition an information leak with the padding word between the floating-point-control word and the floating-point registers in the s390_fp_regs is fixed. Reported-by: Heiko Carstens <heiko.carstens@de.ibm.com> Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel/process.c')
-rw-r--r--arch/s390/kernel/process.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index e1cdd31acabb..7ed0d4e2a435 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -165,7 +165,8 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
165 * save fprs to current->thread.fp_regs to merge them with 165 * save fprs to current->thread.fp_regs to merge them with
166 * the emulated registers and then copy the result to the child. 166 * the emulated registers and then copy the result to the child.
167 */ 167 */
168 save_fp_regs(&current->thread.fp_regs); 168 save_fp_ctl(&current->thread.fp_regs.fpc);
169 save_fp_regs(current->thread.fp_regs.fprs);
169 memcpy(&p->thread.fp_regs, &current->thread.fp_regs, 170 memcpy(&p->thread.fp_regs, &current->thread.fp_regs,
170 sizeof(s390_fp_regs)); 171 sizeof(s390_fp_regs));
171 /* Set a new TLS ? */ 172 /* Set a new TLS ? */
@@ -173,7 +174,9 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
173 p->thread.acrs[0] = frame->childregs.gprs[6]; 174 p->thread.acrs[0] = frame->childregs.gprs[6];
174#else /* CONFIG_64BIT */ 175#else /* CONFIG_64BIT */
175 /* Save the fpu registers to new thread structure. */ 176 /* Save the fpu registers to new thread structure. */
176 save_fp_regs(&p->thread.fp_regs); 177 save_fp_ctl(&p->thread.fp_regs.fpc);
178 save_fp_regs(p->thread.fp_regs.fprs);
179 p->thread.fp_regs.pad = 0;
177 /* Set a new TLS ? */ 180 /* Set a new TLS ? */
178 if (clone_flags & CLONE_SETTLS) { 181 if (clone_flags & CLONE_SETTLS) {
179 unsigned long tls = frame->childregs.gprs[6]; 182 unsigned long tls = frame->childregs.gprs[6];
@@ -205,10 +208,12 @@ int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs)
205 * save fprs to current->thread.fp_regs to merge them with 208 * save fprs to current->thread.fp_regs to merge them with
206 * the emulated registers and then copy the result to the dump. 209 * the emulated registers and then copy the result to the dump.
207 */ 210 */
208 save_fp_regs(&current->thread.fp_regs); 211 save_fp_ctl(&current->thread.fp_regs.fpc);
212 save_fp_regs(current->thread.fp_regs.fprs);
209 memcpy(fpregs, &current->thread.fp_regs, sizeof(s390_fp_regs)); 213 memcpy(fpregs, &current->thread.fp_regs, sizeof(s390_fp_regs));
210#else /* CONFIG_64BIT */ 214#else /* CONFIG_64BIT */
211 save_fp_regs(fpregs); 215 save_fp_ctl(&fpregs->fpc);
216 save_fp_regs(fpregs->fprs);
212#endif /* CONFIG_64BIT */ 217#endif /* CONFIG_64BIT */
213 return 1; 218 return 1;
214} 219}