Re: Everything you want to know about time (Was: Cyrix 6x86MX and Centaur C6 CPUs in 2.1.102)

C. Scott Ananian (
Thu, 21 May 1998 06:13:51 -0400 (EDT)

On Thu, 21 May 1998, Andre Derrick Balsa wrote:

> Actually, there is a simple way to do a RDTSC calibration that will get
> us an accurate measurement of the number of cpu_clock_cycles/jiffy:
> At kernel boot, in time_init (which should run with interrupts
> disabled),
> a) Do a busy wait on the CTC timer until it zeroes.
> b) Now read the TSC.
> c) Do another busy wait on the CTC timer until it zeroes.
> d) Read the TSC again.
> e) The difference in TSC readings is our cpu_clock_cycles/jiffy.
> Maximum time spent on this calibration procedure is just 0.02 seconds,
> and this is at boot time. Note that since both the TSC and the CPU clock
> depend on the same quartz crystal (a 14.31818MHz part), they will never
> drift apart, so there is *no* need to repeat this calibration procedure.

That's really quite nice.
I double-checked, interrupts *are* disabled (from all sources) during
It still doesn't really change the variable-clock-speed problem, though.
(CPU halt, a turbo button, APM slowing the clock...)
But I guess if you screw with your CPU speed you deserve the timing
problems you get.

> > THE EVIL OOPS POTENTIAL: (this is what really matters)
> > ~~~~~~~~~~~~~~~~~~~~~~~~
> > BUT some machines do the unthinkable -- they actually randomly destroy the
> > TSC value during "power-saving." This is the Cyrix bug.
> Sorry if I am being picky, but this is not quite so. The Cyrix doesn't
> destroy the TSC or anything of the sort.

Sorry, but I *am* right. Look carefully at the code. It is *impossible*
for the Cyrix to generate a divide-by-zero Oops (which has been
experimentally verified by numerous sources) *unless* the Cyrix is
zero-ing the top 32 bits of the TSC on HLT. I call that "destroying the

It is impossible to Oops if the Cyrix is just stopping the TSC.
The times will be off, but no Oops.

> We have two cases:
> 1) If the Suspend-on-Halt feature is disabled (default state after a
> reset), the Cyrix 6x86MX will behave just like the Intel part.

I'll believe you there. *BUT* this needs to be documented in big red
letter somewhere: DON'T SUSPEND-ON-HALT. *However* it seems that many
people really really like Suspend-on-halt because it keeps their
processors cooler than the summer sidewalk in new york; it seems being
safe and allowing people to use power-saving on their CPUs is not so
unreasonable an option.

I'll leave this choice up to the Cyrix community. At the moment Linus has
implemented 'prevent-the-Oops,' which I think is a reasonable decision.

> 2) If Suspend-on-Halt is _explicitly_ enabled (e.g. using a utility
> called set6x86), the Cyrix 6x86MX acts like the Centaur C6 step 0, i.e.
> it stops the TSC when Halted.

See above. The Cyrix is trashing the TSC. There's no other way it can

On the same note, if people are seeing Oopsen with the Centaur chips,
which allegedly merely halt the CPU, I'd be very interested to hear about

I wrote:
> > [...](Note that only intra-jiffy
> > times are affected; read the source for the details on how the error is
> > bounded). ...

> The error is bounded as follows:
> maximum 1 jiffy error - 1 microsecond over 1 jiffy. Or if you prefer,
> 100% over 1 jiffy, 50% over 2 jiffies, etc...

Right. I'm bored, I'll recap for the interested why this is so:
* Due to possible jiffies inconsistencies, we need to check
* the result so that we'll get a timer that is monotonic.
if (edx >= USECS_PER_JIFFY)

return edx;
So if do_fast_gettimeoffset() computes a totally bogus value, it is hard
limited to "just before the next jiffy." Each jiffy increments the time
by USECS_PER_JIFFY since the last jiffy time, ignoring the gettimeoffset
values altogether. So the error will never be larger than (one jiffy
minus one microsecond), as you noted.

> BTW if we are concerned with the time it takes for
> gettimeofday() to execute, _this_ cumulative average algorithm in
> do_fast_gettimeoffset() is a low performance solution.

Well, 100 times a second is not really *often* by CPU standards...
..but I agree, if we can do this *just once,* we probably should.

> if (machine_supports_tsc)
> show_MegaHertz_rating
> else
> show_Bogomips_rating
> should go a long way to solve the confusion in many people's minds about
> bogomips, MHz and CPU performance...

Heaven help us if some manufacturer decides to over- or under- clock their

[more info re: divide-by-zero from TSC halt -vs- divide-by-zero by TSC
trash: The *only way* you could get a divide-by-zero from a HALTED (not
trashed) TSC is if the *average* "cycles per jiffy" is less than 1. That
means you have to spend a substantial portion of your total uptime in a
completely halted state (no TSC advancement *at all*, not even during the
jiffy handler), and once the Oopsen start they should never stop (maybe a
slight respite if the TSC advances during the printk of the Oops, but you
get my point). If *this* is what's happening, the Cyrix CPU is not just
buggy, it's *seriously screwed*.]
@ @
C. Scott Ananian: / Declare the Truth boldly and
Laboratory for Computer Science/Crypto / without hindrance.
Massachusetts Institute of Technology /META-PARRESIAS AKOLUTOS:Acts 28:31
-.-. .-.. .. ..-. ..-. --- .-. -.. ... -.-. --- - - .- -. .- -. .. .- -.
PGP key available via finger and from

To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to