diff options
author | Hendrik Brueckner <brueckner@linux.vnet.ibm.com> | 2015-06-11 09:33:54 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2015-07-22 03:58:00 -0400 |
commit | 904818e2f229f3d94ec95f6932a6358c81e73d78 (patch) | |
tree | 8e08f576b000b18b181b617cd0d12a6649a26556 /arch/s390/kernel/traps.c | |
parent | 96b2d7a83a27fbae10fc57c39577a7e2689d9f0a (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.c | 24 |
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 | ||
25 | int show_unhandled_signals = 1; | 25 | int show_unhandled_signals = 1; |
@@ -227,7 +227,6 @@ DO_ERROR_INFO(specification_exception, SIGILL, ILL_ILLOPN, | |||
227 | int alloc_vector_registers(struct task_struct *tsk) | 227 | int 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 | } |