void vector_exception(struct pt_regs *regs) { int si_code, vic; if (!MACHINE_HAS_VX) { do_trap(regs, SIGILL, ILL_ILLOPN, "illegal operation"); return; } /* get vector interrupt code from fpc */ save_fpu_regs(); vic = (current->thread.fpu.fpc & 0xf00) >> 8; switch (vic) { case 1: /* invalid vector operation */ si_code = FPE_FLTINV; break; case 2: /* division by zero */ si_code = FPE_FLTDIV; break; case 3: /* overflow */ si_code = FPE_FLTOVF; break; case 4: /* underflow */ si_code = FPE_FLTUND; break; case 5: /* inexact */ si_code = FPE_FLTRES; break; default: /* unknown cause */ si_code = 0; } do_trap(regs, SIGFPE, si_code, "vector exception"); }
int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) { size_t fpu_regs_size; *dst = *src; /* * If the vector extension is available, it is enabled for all tasks, * and, thus, the FPU register save area must be allocated accordingly. */ fpu_regs_size = MACHINE_HAS_VX ? sizeof(__vector128) * __NUM_VXRS : sizeof(freg_t) * __NUM_FPRS; dst->thread.fpu.regs = kzalloc(fpu_regs_size, GFP_KERNEL|__GFP_REPEAT); if (!dst->thread.fpu.regs) return -ENOMEM; /* * Save the floating-point or vector register state of the current * task and set the CIF_FPU flag to lazy restore the FPU register * state when returning to user space. */ save_fpu_regs(); dst->thread.fpu.fpc = current->thread.fpu.fpc; memcpy(dst->thread.fpu.regs, current->thread.fpu.regs, fpu_regs_size); return 0; }
void data_exception(struct pt_regs *regs) { __u16 __user *location; int signal = 0; location = get_trap_ip(regs); save_fpu_regs(); /* Check for vector register enablement */ if (MACHINE_HAS_VX && !is_vx_task(current) && (current->thread.fpu.fpc & FPC_DXC_MASK) == 0xfe00) { alloc_vector_registers(current); /* Vector data exception is suppressing, rewind psw. */ regs->psw.addr = __rewind_psw(regs->psw, regs->int_code >> 16); clear_pt_regs_flag(regs, PIF_PER_TRAP); return; }
int alloc_vector_registers(struct task_struct *tsk) { __vector128 *vxrs; freg_t *fprs; /* Allocate vector register save area. */ vxrs = kzalloc(sizeof(__vector128) * __NUM_VXRS, GFP_KERNEL|__GFP_REPEAT); if (!vxrs) return -ENOMEM; preempt_disable(); if (tsk == current) save_fpu_regs(); /* Copy the 16 floating point registers */ convert_fp_to_vx(vxrs, tsk->thread.fpu.fprs); fprs = tsk->thread.fpu.fprs; tsk->thread.fpu.vxrs = vxrs; tsk->thread.fpu.flags |= FPU_USE_VX; kfree(fprs); preempt_enable(); return 0; }
/* Store registers needed to create the signal frame */ static void store_sigregs(void) { save_access_regs(current->thread.acrs); save_fpu_regs(); }