A follow-up to r288492. In fact, revert the mentioned commit for

pre-VFPv3 processors, since they do require software support code to
handle denormals.  For VFPv3 and later, enable flush-to-zero if
hardware does not claim full denormals arithmetic support by VMVFR1_FZ
field in mvfr1 register.

The end result is that we do use correct fpu environment on Cortexes
with VFPv3, while ARM11 (e.g. rpi) is in non-compliant flush-to-zero
mode.  At least CPUs without complete hardware implementation of
IEEE 754 do not cause unhandled floating point exception on underflow,
as it was before r288492.

Noted by:	ian
Tested by:	gjb
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
This commit is contained in:
Konstantin Belousov 2015-10-07 09:12:49 +00:00
parent ca587fdaac
commit c890751da6
3 changed files with 15 additions and 1 deletions

View File

@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include <machine/armreg.h>
#include <machine/frame.h>
#include <machine/fp.h>
#include <machine/md_var.h>
#include <machine/pcb.h>
#include <machine/undefined.h>
#include <machine/vfp.h>
@ -128,6 +129,15 @@ vfp_init(void)
tmp = fmrx(mvfr1);
PCPU_SET(vfpmvfr1, tmp);
if (PCPU_GET(cpuid) == 0) {
if ((tmp & VMVFR1_FZ_MASK) == 0x1) {
/* Denormals arithmetic support */
initial_fpscr &= ~VFPSCR_FZ;
thread0.td_pcb->pcb_vfpstate.fpscr =
initial_fpscr;
}
}
}
/* initialize the coprocess 10 and 11 calls

View File

@ -85,6 +85,8 @@ __FBSDID("$FreeBSD$");
CTASSERT(sizeof(struct switchframe) == 48);
CTASSERT(sizeof(struct trapframe) == 80);
uint32_t initial_fpscr = VFPSCR_DN | VFPSCR_FZ;
/*
* Finish a fork operation, with process p2 nearly set up.
* Copy and update the pcb, set up the stack so that the child
@ -134,7 +136,7 @@ cpu_fork(register struct thread *td1, register struct proc *p2,
pcb2->pcb_regs.sf_sp = STACKALIGN(td2->td_frame);
pcb2->pcb_vfpcpu = -1;
pcb2->pcb_vfpstate.fpscr = VFPSCR_DN;
pcb2->pcb_vfpstate.fpscr = initial_fpscr;
tf = td2->td_frame;
tf->tf_spsr &= ~PSR_C;

View File

@ -71,4 +71,6 @@ void dump_add_page(vm_paddr_t);
void dump_drop_page(vm_paddr_t);
int minidumpsys(struct dumperinfo *);
extern uint32_t initial_fpscr;
#endif /* !_MACHINE_MD_VAR_H_ */