Subject: config option vs. run-time detection (the debate continues ...)

From: Jun Sun <[email-masked]>
Date: Thu, 08 Feb 2001 12:27:33 -0800

I love this topic!

Instead of replying to 10 different emails, I decide to sort out my best
understanding of this topic and list them here, including some of MY responses
to some of the issues.

Definition:
------------

1. Config option approach :

	In the kernel config menu, one picks one or more CPUs.  One also specifies
whether the CPU(s) have a FPU.

	All FPU related code in kernel is configured in or out based on the CONFIG
setting.

2. run-time detection approach:

	CPU probing code probes CPU and sets has_fpu field in the mips_cpu structure.

	All FPU related code is on a conditional branch based on has_fpu value.

Run-time Detection Approach
---------------------------

Plus:
	. the same kernel image can run on CPUs either with or without a FPU.

Minus:
	. run-time overhead
		a) cpu detection
		b) conditional checking for FPU related code
	. extra code size (FPU detection and conditional branch for FPU related code)
	. do we have a reliable detection method without any help from CONFIG (I am
not 100% sure here)

Config Option Approach
----------------------

Plus:
	. The reverse of the minus for run-time detection approach

Minus:
	. The same kernel image cannot run on CPUs both with and without a FPU.

My Conclusion
--------------

Clearly, it is a trade-off decision based how much one values the minuses and
pluses of both approaches.

While I do agree the minus for run-time detection are not serious ones, I
think the minus for config option is even less serious.  Having the same
kernel image runs on multiple CPUs is very nice.  I just doubt about the
usefulness of requiring the same kernel image to run on CPUs both with a FPU
and without a FPU.  Therefore in the light of minus of the run-time detection
approach, I still favor config option.

(aha, I proved my intuition. It is a theory now. :-0)

Jun

---

From: "Kevin D. Kissell" <[email-masked]>
Date: Thu, 8 Feb 2001 23:06:33 +0100

> I love this topic!

Well, I'm glad *you're* having fun!  ;-)

> understanding of this topic and list them here, including some of MY
responses

As has been noted in other messages in this exchange, whether one
has an FPU or not isn't really the determining factor in including FP
support code in the kernel.  The bulk of it is the emulator, and the
emulator needs to be there if you want to execute binaries built
to include MIPS FP instructions, whether in full emulation or using
the FPU (for the denormal cases, etc.).

So your CONFIG option would really be to say, regardless of
the CPU, whether your kernel can handle an FPU-ful userland,
or is stripped down to support only 100% integer binaries.

> All FPU related code is on a conditional branch based on has_fpu value.

Again, the FPU-related code has to be there any time you're
going to run FP binaries.  The MIPS_CPU_FPU bit simply
tells the kernel how/when to use it.

...

> and without a FPU.

If you're building kernels for a workstation, that may be
true.  If you're building kernels for a testbed where you're
swapping CPU modules, it's actually rather nice to have
a single kernel that boots on any of them.  I personally
find myself in this situation.  Or to provide a less lab-oriented
example, NEC has the R43xx family which have FPUs,
and Toshiba markets some R49xx parts that are pin-compatible
but cheaper - because they have no FPU.   If I were building
a Linux-based system around either one, memory permitting,
I would want to  have a kernel that could cope with either of
them, to simplify the product management problem if I ever
ended up wanting to cut over from one to the other.

            Kevin K.

---

From: Jun Sun <[email-masked]>
Date: Thu, 08 Feb 2001 14:58:05 -0800

> the FPU (for the denormal cases, etc.).

That needs a little more explanation.

. When I say "All FPU related code", I really meant FPU code which is not a
part of FPU emaulator.  One example is the code in exit_thread()
(arch/mips/process.c) as brough up by flo.  I believe there are also such code
in ptrace.c.

. Regarding whether we should have FPU emulator, I think it should be a
separate CONFIG option.  It is orthorgal to HAS_FPU option.

In other words, we will have four combinations:

 a) HAS_FPU & FPU_EMULATION - which is necessary when FPU is not a full
implementation.

 b) !HAS_FPU & FPU_EMULATION - which allows one to run fpu-ful userland
application

 c) HAS_FPU & !FPU_EMULATION - when FPU is a full implementaion (or use the
old incomplete emaulation?)

 d) !HAS_FPU & !FPU_EMULATION - it mandates non-fpu-ful userland (which to me
is perfectly fine)

I start to feel a little "shaky" here as I have not written any FPU code. 
Will such a classification make life easier or worse?  Is there any
feasibility issue here?

> ended up wanting to cut over from one to the other.

I think this example shifted my bias a little bit, although it has changed it
yet.

Are we confident we can do a clean run-time detection of all existing CPUs?

Jun

---

From: "Kevin D. Kissell" <[email-masked]>
Date: Fri, 9 Feb 2001 01:25:10 +0100

> (arch/mips/process.c) as brough up by flo.  I believe there are also such
code

Understood.  My point is that that code can be lumped with
the emulator as the set of support needed to run FPU-full
binaries.  Even with an emulator, one needs to manage
and communicate FP state.  The only difference is that
the "floating point registers" are in the thread structure,
not in the CPU.

> old incomplete emaulation?)

We're talking about MIPS/Linux here.  To the best of my knowledge
there are *no* "full" implementations of IEEE floating point on
a MIPS CPU.  The number of unimplemented cases varies
somewhat from design to design, but I know of no MIPS CPU
where it is a null set.

> Will such a classification make life easier or worse?  Is there any

It's not so much that I doubt the feasibility, I just wonder
if there's any point to adding the complexity.  As noted
above, if you're going to support FP-full binaries, you
have to support the processor model of FPU.  The user
will be manipulating what he sees as FP registers, and
all of the state, signal, and context management logic
associated with them has to be there regardless of whether
they exist in the CPU or in the kernel.  It's true that there are
a few paths through the code, the ones that actually load
and store the FP registers, that are distinct.  Those could
certainly be suppressed at compile time if you wanted a
kernel that would never allow a real FPU to be used,
but the memory savings would be smaller than you seem
to think.  It's not "HAS_FPU" versus "EMULATOR",
it's "SUPPORTS_FP" and "HAS_FPU".

But my main objection to treating the two options as
orthogonal is that your (c) case above will simply
create kernels that are guaranteed fail for some
cases of IEEE math.  It's just not good engineering
to give people a 25% chance of building a kernel
that seems to be just fine, at first...

My own recommendation would be to either have
full FP support for binaries or none at all.  If someone
really wants to put the FPU-specific assembler
routines under a different conditional, that's cool, but
the configuration options should be such that the
(c) cannot be generated by the config scripts.

            Regards,

            Kevin K.

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Fri, 9 Feb 2001 12:48:10 +0100 (MET)

> it's "SUPPORTS_FP" and "HAS_FPU".

 Let me remind the actual problem the discussion started from was whether
we want to hardcode FP hw presence based on a CPU identification or to
check for it explicitly.  I hope we agree the latter is saner.

 But the code that needs to know whether there is a real FPU present is
indeed minimal (as it should be) thus the gain from removing the detection
altogether in favour to a config option is at least questionable if not
insane. 

> (c) cannot be generated by the config scripts.

 I think I may research what the gain from leaving parts of the FPU
emulator apart would be for systems that have FP hw.  It's not a priority
task for me at the moment -- the current configuration works and having
unused code in a running kernel is ugly but non-fatal. 

  Maciej

-- 
+  Maciej W. Rozycki, Technical University of Gdansk, Poland   +
+--------------------------------------------------------------+
+        e-mail: [email-masked], PGP key available        +

---

From: "Kevin D. Kissell" <[email-masked]>
Date: Fri, 9 Feb 2001 13:56:44 +0100

> check for it explicitly.  I hope we agree the latter is saner.

Absolutely.

> altogether in favour to a config option is at least questionable if not

Well, I might not have put it that strongly, but I quite agree.

> emulator apart would be for systems that have FP hw.

Surprisingly little.  Basically, you could remove emulation
for moves, loads, and stores.  Any instruction that actually
computes a value can potentially turn out to be unimplemented,
depending on the inputs.  If you *knew* you had an FPU, you
could also make the emulation fractionallly more efficient by
having it operate directly on the FP registers.  When the current
kernels emulate an instruction that failed on a HW FPU,
they copy the HW FPU state into the software FPU
registers, invoke the emulator, and when the emulation
has completed, restore the HW FPU state.  It made for
a clean interface to do things that way, and my
judgement was that the operation was too infrequent
to justify complicating things further.

> It's not a priority

"If it ain't broke..."

            Kevin K.

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Fri, 9 Feb 2001 14:06:46 +0100 (MET)

> "If it ain't broke..."

 Well, it's actually one of strengths of Linux we break things from time
to time to make them better.

---

From: Jun Sun <[email-masked]>
Date: Fri, 09 Feb 2001 11:59:18 -0800

> altogether in favour to a config option is at least questionable if not

Do you like run-time detection better because it allows a kernel to run on
CPUs both with a FPU and without a FPU?  Or there is something else to it?

Another question.  I know with mips32 and mips64 we can do run-time detection
reliably.  What about other existing processors?

Jun

---

From: Florian Lohoff <[email-masked]>
Date: Fri, 9 Feb 2001 20:58:38 +0100

>  b) !HAS_FPU & FPU_EMULATION - which allows one to run fpu-ful userland

These 2 cases are perfectly good 

>  d) !HAS_FPU & !FPU_EMULATION - it mandates non-fpu-ful userland (which to me

These 2 cases present a user/developer who decided not to have any
fpu support kernel/cpu wise. Kill his apps if using "illegal" instructions.

Flo
-- 
Florian Lohoff                  [email-masked]             +49-5201-669912
     Why is it called "common sense" when nobody seems to have any?

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Fri, 9 Feb 2001 21:39:29 +0100 (MET)

> CPUs both with a FPU and without a FPU?  Or there is something else to it?

 Nope.  There are certain explicit actions that are to be performed by the
kernel if a real FPU is present, such as saving and restoring its
registers or setting the control register.  Therefore the kernel has to
know if a real part is present and act accordingly.  Maintaining a table
of all CPU ids ever manufactured and manually setting the FPU presence bit
is unreliable, especially as there are chips which cannot be classified
this way, e.g. knowing your CPU is an R3000A you don't know if an R3010A
FPU is soldered as well or not. 

> reliably.  What about other existing processors?

 I've sent a quote from an IDT manual recently.  It recommended to use the
FPU implementation ID to check if an FP hw is present.  I believe it
should work for any sane implementation of a MIPS CPU.  See the mail for
details. 

  Maciej

---

From: Jun Sun <[email-masked]>
Date: Fri, 09 Feb 2001 13:31:07 -0800

> FPU is soldered as well or not.

Apparently you did not read my first email on this thread. :-)

I agree "Maintaining a table of all CPU ids ever manufactured and manually
setting the FPU presence bit is unreliable ...".

I was debating about how we let kernel know if there is a real FPU:

  a) an explicit config option, CONFIG_HAS_FPU, (which is not associated with
PrID), plus "#ifdef CONFIG_HAS_FPU ..." code.  Or

  b) have run-time detection and many "if .. then .." code.

I listed some pro's and con's for both of them in my first email.  Right now,
I found myself not having a strong preference but still biased towards config
option approach ( - as if that really matters. :-0)

> should work for any sane implementation of a MIPS CPU.  See the mail for

I actually don't understand your IDT quote.  It requires one to call mfc1 to
get FCR0.  On many CPUs without a FPU, this will generate an exception.  Are
you suggesting that we should catch the exception and from that we conclude
there is no FPU present?

Jun

---

From: "Kevin D. Kissell" <[email-masked]>
Date: Fri, 9 Feb 2001 23:12:00 +0100

> should work for any sane implementation of a MIPS CPU.  See the mail for

The best method I know for post-R3000 CPUs is to
write and read back the CU1 bit of the Status register.
CPUs without an integrated FPU will not have a flip-flop
for the bit, and will read back a 0 even after writing a 1.
There was never any architectural requirement that
this be so, however, and this cannot be absolutely
guaranteed to work.  If anyone has a counter-example,
however, I'd be interested in hearing about it.

            Kevin K.

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Sat, 10 Feb 2001 10:01:50 +0100 (MET)

> option approach ( - as if that really matters. :-0)

 Well, the number of places a run-time condition exist is small and they
are not performance-critical. 

> you suggesting that we should catch the exception and from that we conclude

 I don't have an FPU-less system and I can't check such code.  I need to
depend on others (I couldn't test all possible configurations anyway).  If
we have a chance to get an exception we have to catch it, of course
(that's trivial to handle in Linux).

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Sat, 10 Feb 2001 10:05:28 +0100 (MET)

> however, I'd be interested in hearing about it.

 OK, then we may try to toggle CU1 and only if that succeeds check the FPU
implementation id.  Thanks for the point.

---

From: Jun Sun <[email-masked]>
Date: Mon, 12 Feb 2001 10:21:45 -0800

"Maciej W. Rozycki" wrote:
> depend on others (I couldn't test all possible configurations anyway).

However, with CONFIG_HAS_FPU approach I know for sure it will work for any
MIPS CPU, as long as the programmer specifies it correctly. :-)

> If

No effort (as in CONFIG_HAS_FPU approach) is still better than trivial or
small effort ( as in run-time detection).  :-)

---

I am very curious what makes you object to the CONFIG_HAS_FPU approach,
especially you said earlier it was not about the inability to support both FPU
and FPU-less CPUs with the same kernel image.

Jun

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Tue, 13 Feb 2001 19:31:11 +0100 (MET)

> MIPS CPU, as long as the programmer specifies it correctly. :-)

 Tha latter being a BIG if.

> small effort ( as in run-time detection).  :-)

 Regardless of the CONFIG_HAS_FPU option you still need to check if a FPU
is present.

> and FPU-less CPUs with the same kernel image.

 That's pretty orthogonal -- I do not object the CONFIG_HAS_FPU option (I
even favor it, if it could save us unneeded bits), but whether having it
or not, we still have to properly detect FP hardware.  A silent crash or
an obscure oops is not an option in case of a config error.