On Thu, Jan 06, 2000 at 10:12:21AM +0100, Kevin D. Kissell wrote:
> The "setting flush to zero/Unimlemented exception"
> problem is almost certainly due to the fact that the
> DECstation binaries were compiled for R3000-based
> platforms with R3K-style FPUs which have 32 single-precision
> FP regs that can also be treated pairwise as 16
> double-precision registers. I didn't know that the 5000 line
> had R4000 CPUs in them, but on the basis of your reported
> CPU revision number, that's what you've got.
> The default SGI/MIPS Linux kernel startup sets the
> "FR" bit in the CP0.Status register, which enables
> R4000-style FPU registers, which is to say a full
> compliment of 32 double-precision registers. This
> has the side-effect of making the kernel incompatible
> with the distributed mipsel binaries and the distributed
> DECstation root file system, since those binaries which
> do double-precision floating point load their initial values
> from memory as two singles. That works on an R3000
> or an R4000-with-FR=0, but not on an R4000-with-FR=1.
> If FR=1, the data in the registers is garbage, the FP
> ops trap on unimplemented exceptions, which first
> retry the instruction with flush-to-zero mode in a
> desperate hope that that will solve the problem,
> then call the fragmentatary SW emulator in the
> kernel, which only handles a few cases, then
> skip the instruction, printing the console message
> that it "should" have sent a SIGFPE. Hence the
> output. And hence the bizzare behaviour of awk,
> ps, and a number of other basic programs that do
> minimal FP as the system comes up (procps?).
> It took me a while to figure this out when I ran into
> it doing a little-endian port of Linux 2.2.12 to an R5260,
> as you might imagine. Unless things have been drastically
> scrambled for 2.3.x, the code controlling this is in
> arch/mips/kernel/head.S. What we did at MIPS was
> to add a config option to determine which FPU model
> is desired. The truly elegant thing would be to examine
> the a.out file and manage Status.FR dynamically, but
> a quick inspection turned up no clean mechanism in
> the Linux kernel for passing such architecture-dependent
> information from the generic a.out file parsing to the
> thread creation machinery, so that will be a later
> exercise. Thoward the end of the kernel entry point
> (kernel_entry), our revised code looks a bit like this:
Linux _never_ changes the FR flag. In fact it's living in the assumption
that once the firmware hands over the control to the kernel the FR flag
has been configured apropriately. For a 32-bit kernel the binaries available
out there more or less conform to the MIPS ABI which uses the 16/32
register model, that is the kernel expects the FR flag to be cleared.
In firm assumption that due all the practical problems involved with
a non-standard execution model (i.e. 32-bit, o32-style ELF, 32/32
register model and 32-bit gprs) I decieded that in practice nobody will
use this and dumped all the support for it from later 2.3 kernels. That
is the scheduler will no longer try to handle context switching for
the 32/32 fpr model correctly etc.
If that's desired, how about providing a syscall which allows to manipulate
this and possibly other bits?
Btw... Thanks for posting. You pointed my nose at the fact that this bug
actually exists for the 64-bit kernel - and there is actually a real world
bug because we can mix 32-bit and 64-bit binaries.