On Fri, 28 Sep 2012, [utf-8] Dag-Erling Sm??rgrav wrote:

Bruce Evans <[email protected]> writes:
"Dag-Erling Sm??rgrav" <[email protected]> writes:
RW <[email protected]> writes:
binuptime(&bt);
return (bt.frac ^ bt.sec);
Why the heck does it xor the integer and fractional parts together?
Because most of the entropy is in the fractional part,

This is not about entropy, it's about implementing get_cyclecount() on a
platform that doesn't have a TSC.  It's supposed to be monotonic, and
this implementation clearly isn't.  Even when bt.sec is small enough

Its monotonicity and documentation of same is a bug.

that it doesn't affect significant digits of bt.frac (which should be
most of the time, unless the resolution of the underlying timecounter
exceeds ~2^32 Hz), get_cyclecount() will go backward every time a new
second ticks over.

Its implementation demonstrates that it was never actually monotonic.
Even rdtsc() isn't necessarily monotonic.

Its comment in at least the i386 version still says that it "Return[s]
contents of an in-cpu fast counter as a sort of "bogo-time" for random-
harvesting purposes".  This has rotted in various ways:
- on i386 without tsc_present, it never used an in-cpu fast counter
  (since there is none)
- on i386, without tsc_present, it now uses the generic cpu_ticks()
  and gets whatever that gives, which happens to be a more monotonic
  less bogus time that before, and which doesn't have the xor hack.
- on i386, with tsc_present, it now uses the generic cpu_ticks()
  and gets whatever that gives, which happens to be the same in-cpu
  fast counter as before.
It shouldn't be commenting about what cpu_ticks() [doesn't] do.
- its man page says that it uses a "register available in most modern
  CPUs to return a value that is monotonically increasing inside each
  CPU", and explicitly documents that each CPU gives a separate monotonic
  sequence.  A strict reading of this says that it doesn't exist on
  non-modern CPUs or on some modern CPUS.  Bugs in this include:
  - over-specification of implementation details.  Lots of bugs in the
    details:
    - at least in i386, the value isn't necessarily increasing even with
      in each CPU, since rdtsc() isn't serialized and maybe something
      resets the register.  The implementation just uses rdtsc() without
      worrying about these points.
    - on more modern CPUs, the values are synced, so the sequences aren't
      separate.
  - guaranteeing monotonicity.
- it is now abused for non-random-harvesting purposes, and some of these
  require it to be monotonic.  These places mostly just want a timestamp
  for debugging and should be using microtime().  See one of my old mails
  for full details of this and more details of the bogusness of
  get_cyclecount().

I should have objected more strongly when it was implemented.  Just using
binuptime() was adequate iff the timecounter hardware is the same as
the cycle counter (TSC on x86).  A TSC usable for timecounter hardware is
normal now.  I don't like cpu_tick() either, but it solves the efficiency
problem with the timecounter hardware not being the cycle counter.  It
solves them for use mainly in thread runtime accounting, but is usable
for get_cyclecount() too, and is in fact used for get_cyclecount() on i386
(get_cyclecount() just wraps it and no one except bde cares about the
inefficiency of this).  cpu_tick() is undocumented, so there are no bugs
in its man page to fix.

Bruce
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-security
To unsubscribe, send any mail to "[email protected]"

Reply via email to