version 1.41.4.5, 2017/08/28 17:51:32 |
version 1.42, 2015/02/09 07:55:52 |
Line 95 load_vfpregs(const struct vfpreg *fregs) |
|
Line 95 load_vfpregs(const struct vfpreg *fregs) |
|
case FPU_VFP_CORTEXA9: |
case FPU_VFP_CORTEXA9: |
case FPU_VFP_CORTEXA15: |
case FPU_VFP_CORTEXA15: |
case FPU_VFP_CORTEXA15_QEMU: |
case FPU_VFP_CORTEXA15_QEMU: |
case FPU_VFP_CORTEXA53: |
|
case FPU_VFP_CORTEXA57: |
|
#endif |
#endif |
load_vfpregs_hi(fregs->vfp_regs); |
load_vfpregs_hi(fregs->vfp_regs); |
#ifdef CPU_ARM11 |
#ifdef CPU_ARM11 |
Line 119 save_vfpregs(struct vfpreg *fregs) |
|
Line 117 save_vfpregs(struct vfpreg *fregs) |
|
case FPU_VFP_CORTEXA9: |
case FPU_VFP_CORTEXA9: |
case FPU_VFP_CORTEXA15: |
case FPU_VFP_CORTEXA15: |
case FPU_VFP_CORTEXA15_QEMU: |
case FPU_VFP_CORTEXA15_QEMU: |
case FPU_VFP_CORTEXA53: |
|
case FPU_VFP_CORTEXA57: |
|
#endif |
#endif |
save_vfpregs_hi(fregs->vfp_regs); |
save_vfpregs_hi(fregs->vfp_regs); |
#ifdef CPU_ARM11 |
#ifdef CPU_ARM11 |
Line 198 vfp_fpscr_handler(u_int address, u_int i |
|
Line 194 vfp_fpscr_handler(u_int address, u_int i |
|
if (pcb->pcb_vfp.vfp_fpexc & VFP_FPEXC_EN) |
if (pcb->pcb_vfp.vfp_fpexc & VFP_FPEXC_EN) |
return 1; |
return 1; |
|
|
if (__predict_false(!vfp_used_p(l))) { |
if (__predict_false(!vfp_used_p())) { |
pcb->pcb_vfp.vfp_fpscr = vfp_fpscr_default; |
pcb->pcb_vfp.vfp_fpscr = vfp_fpscr_default; |
} |
} |
#endif |
#endif |
Line 215 vfp_fpscr_handler(u_int address, u_int i |
|
Line 211 vfp_fpscr_handler(u_int address, u_int i |
|
} |
} |
|
|
curcpu()->ci_vfp_evs[0].ev_count++; |
curcpu()->ci_vfp_evs[0].ev_count++; |
|
|
frame->tf_pc += INSN_SIZE; |
frame->tf_pc += INSN_SIZE; |
return 0; |
return 0; |
} |
} |
Line 269 vfp_attach(struct cpu_info *ci) |
|
Line 265 vfp_attach(struct cpu_info *ci) |
|
cpacr |= __SHIFTIN(CPACR_ALL, cpacr_vfp2); |
cpacr |= __SHIFTIN(CPACR_ALL, cpacr_vfp2); |
armreg_cpacr_write(cpacr); |
armreg_cpacr_write(cpacr); |
|
|
arm_isb(); |
|
|
|
/* |
/* |
* If we could enable them, then they exist. |
* If we could enable them, then they exist. |
*/ |
*/ |
Line 321 vfp_attach(struct cpu_info *ci) |
|
Line 315 vfp_attach(struct cpu_info *ci) |
|
case FPU_VFP_CORTEXA9: |
case FPU_VFP_CORTEXA9: |
case FPU_VFP_CORTEXA15: |
case FPU_VFP_CORTEXA15: |
case FPU_VFP_CORTEXA15_QEMU: |
case FPU_VFP_CORTEXA15_QEMU: |
case FPU_VFP_CORTEXA53: |
|
case FPU_VFP_CORTEXA57: |
|
if (armreg_cpacr_read() & CPACR_V7_ASEDIS) { |
if (armreg_cpacr_read() & CPACR_V7_ASEDIS) { |
model = "VFP 4.0+"; |
model = "VFP 4.0+"; |
} else { |
} else { |
Line 354 vfp_attach(struct cpu_info *ci) |
|
Line 346 vfp_attach(struct cpu_info *ci) |
|
((f0 & ARM_MVFR0_EXCEPT_MASK) ? ", exceptions" : ""), |
((f0 & ARM_MVFR0_EXCEPT_MASK) ? ", exceptions" : ""), |
((f1 & ARM_MVFR1_D_NAN_MASK) ? ", NaN propagation" : ""), |
((f1 & ARM_MVFR1_D_NAN_MASK) ? ", NaN propagation" : ""), |
((f1 & ARM_MVFR1_FTZ_MASK) ? ", denormals" : "")); |
((f1 & ARM_MVFR1_FTZ_MASK) ? ", denormals" : "")); |
aprint_debug("vfp%d: mvfr: [0]=%#x [1]=%#x\n", |
aprint_verbose("vfp%d: mvfr: [0]=%#x [1]=%#x\n", |
device_unit(ci->ci_dev), f0, f1); |
device_unit(ci->ci_dev), f0, f1); |
if (CPU_IS_PRIMARY(ci)) { |
if (CPU_IS_PRIMARY(ci)) { |
if (f0 & ARM_MVFR0_ROUNDING_MASK) { |
if (f0 & ARM_MVFR0_ROUNDING_MASK) { |
Line 384 vfp_attach(struct cpu_info *ci) |
|
Line 376 vfp_attach(struct cpu_info *ci) |
|
install_coproc_handler(VFP_COPROC, vfp_handler); |
install_coproc_handler(VFP_COPROC, vfp_handler); |
install_coproc_handler(VFP_COPROC2, vfp_handler); |
install_coproc_handler(VFP_COPROC2, vfp_handler); |
#ifdef CPU_CORTEX |
#ifdef CPU_CORTEX |
if (cpu_neon_present) |
install_coproc_handler(CORE_UNKNOWN_HANDLER, neon_handler); |
install_coproc_handler(CORE_UNKNOWN_HANDLER, neon_handler); |
|
#endif |
#endif |
} |
} |
|
|
Line 405 vfp_handler(u_int address, u_int insn, t |
|
Line 396 vfp_handler(u_int address, u_int insn, t |
|
} |
} |
|
|
/* |
/* |
* If we are just changing/fetching FPSCR, don't bother loading it |
* If we are just changing/fetching FPSCR, don't bother loading it. |
* just emulate the instruction. |
|
*/ |
*/ |
if (!vfp_fpscr_handler(address, insn, frame, fault_code)) |
if (!vfp_fpscr_handler(address, insn, frame, fault_code)) |
return 0; |
return 0; |
|
|
/* |
/* |
* If we already own the FPU and it's enabled (and no exception), raise |
|
* SIGILL. If there is an exception, drop through to raise a SIGFPE. |
|
*/ |
|
if (curcpu()->ci_pcu_curlwp[PCU_FPU] == curlwp |
|
&& (armreg_fpexc_read() & (VFP_FPEXC_EX|VFP_FPEXC_EN)) == VFP_FPEXC_EN) |
|
return 1; |
|
|
|
/* |
|
* Make sure we own the FP. |
* Make sure we own the FP. |
*/ |
*/ |
pcu_load(&arm_vfp_ops); |
pcu_load(&arm_vfp_ops); |
Line 437 vfp_handler(u_int address, u_int insn, t |
|
Line 419 vfp_handler(u_int address, u_int insn, t |
|
*/ |
*/ |
armreg_fpexc_write(fpexc & ~(VFP_FPEXC_EX|VFP_FPEXC_FSUM)); |
armreg_fpexc_write(fpexc & ~(VFP_FPEXC_EX|VFP_FPEXC_FSUM)); |
|
|
pcu_save(&arm_vfp_ops, curlwp); |
pcu_save(&arm_vfp_ops); |
|
|
/* |
/* |
* XXX Need to emulate bounce instructions here to get correct |
* XXX Need to emulate bounce instructions here to get correct |
Line 486 neon_handler(u_int address, u_int insn, |
|
Line 468 neon_handler(u_int address, u_int insn, |
|
if (fault_code != FAULT_USER) |
if (fault_code != FAULT_USER) |
panic("NEON fault in non-user mode"); |
panic("NEON fault in non-user mode"); |
|
|
/* if we already own the FPU and it's enabled, raise SIGILL */ |
|
if (curcpu()->ci_pcu_curlwp[PCU_FPU] == curlwp |
|
&& (armreg_fpexc_read() & VFP_FPEXC_EN) != 0) |
|
return 1; |
|
|
|
pcu_load(&arm_vfp_ops); |
pcu_load(&arm_vfp_ops); |
|
|
/* Need to restart the faulted instruction. */ |
/* Need to restart the faulted instruction. */ |
Line 549 vfp_state_load(lwp_t *l, u_int flags) |
|
Line 526 vfp_state_load(lwp_t *l, u_int flags) |
|
|
|
if (fregs->vfp_fpexc & VFP_FPEXC_EX) { |
if (fregs->vfp_fpexc & VFP_FPEXC_EX) { |
/* Need to restore the exception handling state. */ |
/* Need to restore the exception handling state. */ |
armreg_fpinst_write(fregs->vfp_fpinst); |
armreg_fpinst2_write(fregs->vfp_fpinst2); |
if (fregs->vfp_fpexc & VFP_FPEXC_FP2V) |
if (fregs->vfp_fpexc & VFP_FPEXC_FP2V) |
armreg_fpinst2_write(fregs->vfp_fpinst2); |
armreg_fpinst_write(fregs->vfp_fpinst); |
} |
} |
} |
} |
|
|
Line 606 vfp_state_release(lwp_t *l) |
|
Line 583 vfp_state_release(lwp_t *l) |
|
} |
} |
|
|
void |
void |
vfp_savecontext(lwp_t *l) |
vfp_savecontext(void) |
{ |
{ |
pcu_save(&arm_vfp_ops, l); |
pcu_save(&arm_vfp_ops); |
} |
} |
|
|
void |
void |
vfp_discardcontext(lwp_t *l, bool used_p) |
vfp_discardcontext(bool used_p) |
{ |
{ |
pcu_discard(&arm_vfp_ops, l, used_p); |
pcu_discard(&arm_vfp_ops, used_p); |
} |
} |
|
|
bool |
bool |
vfp_used_p(const lwp_t *l) |
vfp_used_p(void) |
{ |
{ |
return pcu_valid_p(&arm_vfp_ops, l); |
return pcu_valid_p(&arm_vfp_ops); |
} |
} |
|
|
void |
void |
vfp_getcontext(struct lwp *l, mcontext_t *mcp, int *flagsp) |
vfp_getcontext(struct lwp *l, mcontext_t *mcp, int *flagsp) |
{ |
{ |
if (vfp_used_p(l)) { |
if (vfp_used_p()) { |
const struct pcb * const pcb = lwp_getpcb(l); |
const struct pcb * const pcb = lwp_getpcb(l); |
|
pcu_save(&arm_vfp_ops); |
pcu_save(&arm_vfp_ops, l); |
|
mcp->__fpu.__vfpregs.__vfp_fpscr = pcb->pcb_vfp.vfp_fpscr; |
mcp->__fpu.__vfpregs.__vfp_fpscr = pcb->pcb_vfp.vfp_fpscr; |
memcpy(mcp->__fpu.__vfpregs.__vfp_fstmx, pcb->pcb_vfp.vfp_regs, |
memcpy(mcp->__fpu.__vfpregs.__vfp_fstmx, pcb->pcb_vfp.vfp_regs, |
sizeof(mcp->__fpu.__vfpregs.__vfp_fstmx)); |
sizeof(mcp->__fpu.__vfpregs.__vfp_fstmx)); |
Line 640 vfp_getcontext(struct lwp *l, mcontext_t |
|
Line 616 vfp_getcontext(struct lwp *l, mcontext_t |
|
void |
void |
vfp_setcontext(struct lwp *l, const mcontext_t *mcp) |
vfp_setcontext(struct lwp *l, const mcontext_t *mcp) |
{ |
{ |
|
pcu_discard(&arm_vfp_ops, true); |
struct pcb * const pcb = lwp_getpcb(l); |
struct pcb * const pcb = lwp_getpcb(l); |
|
|
pcu_discard(&arm_vfp_ops, l, true); |
|
pcb->pcb_vfp.vfp_fpscr = mcp->__fpu.__vfpregs.__vfp_fpscr; |
pcb->pcb_vfp.vfp_fpscr = mcp->__fpu.__vfpregs.__vfp_fpscr; |
memcpy(pcb->pcb_vfp.vfp_regs, mcp->__fpu.__vfpregs.__vfp_fstmx, |
memcpy(pcb->pcb_vfp.vfp_regs, mcp->__fpu.__vfpregs.__vfp_fstmx, |
sizeof(mcp->__fpu.__vfpregs.__vfp_fstmx)); |
sizeof(mcp->__fpu.__vfpregs.__vfp_fstmx)); |