aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/traps.c
diff options
context:
space:
mode:
authorHendrik Brueckner <brueckner@linux.vnet.ibm.com>2015-06-11 09:33:54 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2015-07-22 03:58:00 -0400
commit904818e2f229f3d94ec95f6932a6358c81e73d78 (patch)
tree8e08f576b000b18b181b617cd0d12a6649a26556 /arch/s390/kernel/traps.c
parent96b2d7a83a27fbae10fc57c39577a7e2689d9f0a (diff)
s390/kernel: introduce fpu-internal.h with fpu helper functions
Introduce a new structure to manage FP and VX registers. Refactor the save and restore of floating point and vector registers with a set of helper functions in fpu-internal.h. Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel/traps.c')
-rw-r--r--arch/s390/kernel/traps.c24
1 files changed, 11 insertions, 13 deletions
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 7bea81d8a363..97598d1876c7 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -19,7 +19,7 @@
19#include <linux/sched.h> 19#include <linux/sched.h>
20#include <linux/mm.h> 20#include <linux/mm.h>
21#include <linux/slab.h> 21#include <linux/slab.h>
22#include <asm/switch_to.h> 22#include <asm/fpu-internal.h>
23#include "entry.h" 23#include "entry.h"
24 24
25int show_unhandled_signals = 1; 25int show_unhandled_signals = 1;
@@ -227,7 +227,6 @@ DO_ERROR_INFO(specification_exception, SIGILL, ILL_ILLOPN,
227int alloc_vector_registers(struct task_struct *tsk) 227int alloc_vector_registers(struct task_struct *tsk)
228{ 228{
229 __vector128 *vxrs; 229 __vector128 *vxrs;
230 int i;
231 230
232 /* Allocate vector register save area. */ 231 /* Allocate vector register save area. */
233 vxrs = kzalloc(sizeof(__vector128) * __NUM_VXRS, 232 vxrs = kzalloc(sizeof(__vector128) * __NUM_VXRS,
@@ -236,11 +235,10 @@ int alloc_vector_registers(struct task_struct *tsk)
236 return -ENOMEM; 235 return -ENOMEM;
237 preempt_disable(); 236 preempt_disable();
238 if (tsk == current) 237 if (tsk == current)
239 save_fp_regs(tsk->thread.fp_regs.fprs); 238 save_fp_regs(tsk->thread.fpu.fprs);
240 /* Copy the 16 floating point registers */ 239 /* Copy the 16 floating point registers */
241 for (i = 0; i < 16; i++) 240 convert_fp_to_vx(vxrs, tsk->thread.fpu.fprs);
242 *(freg_t *) &vxrs[i] = tsk->thread.fp_regs.fprs[i]; 241 tsk->thread.fpu.vxrs = vxrs;
243 tsk->thread.vxrs = vxrs;
244 if (tsk == current) { 242 if (tsk == current) {
245 __ctl_set_bit(0, 17); 243 __ctl_set_bit(0, 17);
246 restore_vx_regs(vxrs); 244 restore_vx_regs(vxrs);
@@ -259,8 +257,8 @@ void vector_exception(struct pt_regs *regs)
259 } 257 }
260 258
261 /* get vector interrupt code from fpc */ 259 /* get vector interrupt code from fpc */
262 asm volatile("stfpc %0" : "=Q" (current->thread.fp_regs.fpc)); 260 asm volatile("stfpc %0" : "=Q" (current->thread.fpu.fpc));
263 vic = (current->thread.fp_regs.fpc & 0xf00) >> 8; 261 vic = (current->thread.fpu.fpc & 0xf00) >> 8;
264 switch (vic) { 262 switch (vic) {
265 case 1: /* invalid vector operation */ 263 case 1: /* invalid vector operation */
266 si_code = FPE_FLTINV; 264 si_code = FPE_FLTINV;
@@ -297,22 +295,22 @@ void data_exception(struct pt_regs *regs)
297 295
298 location = get_trap_ip(regs); 296 location = get_trap_ip(regs);
299 297
300 asm volatile("stfpc %0" : "=Q" (current->thread.fp_regs.fpc)); 298 asm volatile("stfpc %0" : "=Q" (current->thread.fpu.fpc));
301 /* Check for vector register enablement */ 299 /* Check for vector register enablement */
302 if (MACHINE_HAS_VX && !current->thread.vxrs && 300 if (MACHINE_HAS_VX && !is_vx_task(current) &&
303 (current->thread.fp_regs.fpc & FPC_DXC_MASK) == 0xfe00) { 301 (current->thread.fpu.fpc & FPC_DXC_MASK) == 0xfe00) {
304 alloc_vector_registers(current); 302 alloc_vector_registers(current);
305 /* Vector data exception is suppressing, rewind psw. */ 303 /* Vector data exception is suppressing, rewind psw. */
306 regs->psw.addr = __rewind_psw(regs->psw, regs->int_code >> 16); 304 regs->psw.addr = __rewind_psw(regs->psw, regs->int_code >> 16);
307 clear_pt_regs_flag(regs, PIF_PER_TRAP); 305 clear_pt_regs_flag(regs, PIF_PER_TRAP);
308 return; 306 return;
309 } 307 }
310 if (current->thread.fp_regs.fpc & FPC_DXC_MASK) 308 if (current->thread.fpu.fpc & FPC_DXC_MASK)
311 signal = SIGFPE; 309 signal = SIGFPE;
312 else 310 else
313 signal = SIGILL; 311 signal = SIGILL;
314 if (signal == SIGFPE) 312 if (signal == SIGFPE)
315 do_fp_trap(regs, current->thread.fp_regs.fpc); 313 do_fp_trap(regs, current->thread.fpu.fpc);
316 else if (signal) 314 else if (signal)
317 do_trap(regs, signal, ILL_ILLOPN, "data exception"); 315 do_trap(regs, signal, ILL_ILLOPN, "data exception");
318} 316}