Changeset View
Changeset View
Standalone View
Standalone View
sys/arm/arm/vfp.c
Show First 20 Lines • Show All 190 Lines • ▼ Show 20 Lines | if (vfp10_uh.uh_handler == NULL) { | ||||
install_coproc_handler_static(10, &vfp10_uh); | install_coproc_handler_static(10, &vfp10_uh); | ||||
install_coproc_handler_static(11, &vfp11_uh); | install_coproc_handler_static(11, &vfp11_uh); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
SYSINIT(vfp, SI_SUB_CPU, SI_ORDER_ANY, vfp_init, NULL); | SYSINIT(vfp, SI_SUB_CPU, SI_ORDER_ANY, vfp_init, NULL); | ||||
/* start VFP unit, restore the vfp registers from the PCB and retry | /* | ||||
* the instruction | * Start the VFP unit, restore the VFP registers from the PCB and retry | ||||
* the instruction. | |||||
*/ | */ | ||||
static int | static int | ||||
vfp_bounce(u_int addr, u_int insn, struct trapframe *frame, int code) | vfp_bounce(u_int addr, u_int insn, struct trapframe *frame, int code) | ||||
{ | { | ||||
u_int cpu, fpexc; | u_int cpu, fpexc; | ||||
struct pcb *curpcb; | struct pcb *curpcb; | ||||
ksiginfo_t ksi; | ksiginfo_t ksi; | ||||
if ((code & FAULT_USER) == 0) | |||||
panic("undefined floating point instruction in supervisor mode"); | |||||
critical_enter(); | critical_enter(); | ||||
/* | /* | ||||
* If the VFP is already on and we got an undefined instruction, then | * If the VFP is already on and we got an undefined instruction, then | ||||
* something tried to executate a truly invalid instruction that maps to | * something tried to executate a truly invalid instruction that maps to | ||||
* the VFP. | * the VFP. | ||||
*/ | */ | ||||
fpexc = fmrx(fpexc); | fpexc = fmrx(fpexc); | ||||
Show All 17 Lines | if (fpexc & VFPEXC_EX) { | ||||
ksi.ksi_addr = (void *)addr; | ksi.ksi_addr = (void *)addr; | ||||
trapsignal(curthread, &ksi); | trapsignal(curthread, &ksi); | ||||
return 0; | return 0; | ||||
} | } | ||||
return 1; | return 1; | ||||
} | } | ||||
curpcb = curthread->td_pcb; | |||||
if ((code & FAULT_USER) == 0 && | |||||
(curpcb->pcb_fpflags & PCB_FP_KERN) == 0) { | |||||
critical_exit(); | |||||
return (1); | |||||
} | |||||
/* | /* | ||||
* If the last time this thread used the VFP it was on this core, and | * If the last time this thread used the VFP it was on this core, and | ||||
* the last thread to use the VFP on this core was this thread, then the | * the last thread to use the VFP on this core was this thread, then the | ||||
* VFP state is valid, otherwise restore this thread's state to the VFP. | * VFP state is valid, otherwise restore this thread's state to the VFP. | ||||
*/ | */ | ||||
fmxr(fpexc, fpexc | VFPEXC_EN); | fmxr(fpexc, fpexc | VFPEXC_EN); | ||||
curpcb = curthread->td_pcb; | |||||
cpu = PCPU_GET(cpuid); | cpu = PCPU_GET(cpuid); | ||||
if (curpcb->pcb_vfpcpu != cpu || curthread != PCPU_GET(fpcurthread)) { | if (curpcb->pcb_vfpcpu != cpu || curthread != PCPU_GET(fpcurthread)) { | ||||
vfp_restore(curpcb->pcb_vfpsaved); | vfp_restore(curpcb->pcb_vfpsaved); | ||||
curpcb->pcb_vfpcpu = cpu; | curpcb->pcb_vfpcpu = cpu; | ||||
PCPU_SET(fpcurthread, curthread); | PCPU_SET(fpcurthread, curthread); | ||||
} | } | ||||
critical_exit(); | critical_exit(); | ||||
KASSERT(curpcb->pcb_vfpsaved == &curpcb->pcb_vfpstate, | KASSERT((code & FAULT_USER) == 0 || | ||||
curpcb->pcb_vfpsaved == &curpcb->pcb_vfpstate, | |||||
("Kernel VFP state in use when entering userspace")); | ("Kernel VFP state in use when entering userspace")); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Update the VFP state for a forked process or new thread. The PCB will | * Update the VFP state for a forked process or new thread. The PCB will | ||||
* have been copied from the old thread. | * have been copied from the old thread. | ||||
▲ Show 20 Lines • Show All 273 Lines • Show Last 20 Lines |