svn commit: r320901 - in head/sys: amd64/amd64 isa x86/isa

Bruce Evans brde at optusnet.com.au
Wed Jul 19 10:59:48 UTC 2017


On Tue, 18 Jul 2017, Ian Lepore wrote:

> On Tue, 2017-07-18 at 18:08 +1000, Bruce Evans wrote:

>> [lots of stuff about locking and accurate time-setting]
>>
>> Good idea.
>>
>> My inittodr() waits for the seconds register to change.  This
>> increases
>> boot time by an average of 0.5 seconds, but is needed to get a result
>> that is not out of date by an average of 0.5 seconds.  After the
>> seconds
>> register changes, the window for reading the other registers is
>> almost
>> 1 second, but the reads must complete in a few microseconds anyway
>> else
>> the result is still too out of date.  Debugging printf()s show that
>> the reads usually complete in 10-50 usec with low latency (faster on
>> old systems with faster ISA buses).
>>
>
> I was considering adding a tunable to do that for people who don't mind
> the extra time to boot/wakeup.  It's interesting that you label an
> error of a few microseconds as "too out of date", I was thinking that
> reducing the average error from .5s to .005s was good enough.
>
> The .005s number comes from an idea of using a callout that begins as
> soon as interrupts are available that checks for rtc rollover every
> 10ms, with the hopes that it can catch the rollover between the time
> callouts start working and rootfs mount time when inittodr() gets
> called.  If it can catch the rollover happening in that window, it can
> latch the monotonic clock and then use that at inittodr() time to
> calculate the fractional part of the time.  Even if it doesn't catch
> the rollover in that time, it at least has a measurement that sets a
> floor value for the fractional part, reducing the error to something
> less than .5s.

Hmm, my rtcintr() already does essentially that without really trying.
It is designed to fix up the time after "suspension" in ddb breaks the
time by stopping timecounter updates.  The fixed up time is:

    (the rtc time) +
    (the last known good difference between the timecounter time and the
      rtc time) +
    (an adjustment for the drift rate)

My rtcintr() samples the difference and calibrates the drift every 64
seconds.  It uses rtc update interrupts every second to get precise
timing for the sampling and to avoid having to wait for updates to
complete before sampling.

Initially, the offset and drift are unknown, but using 0 for them would
give similar functionality to inittodr().

> I have no idea yet how much time elapses between interrupts coming
> online and the first inittodr() call on a typical modern x86
> system.  For all my arm systems with nfsroot it's several seconds.  If
> it averages a few milliseconds on x86 systems, it isn't useful enough
> to justify the extra work.  If it's typically half a second or more it
> probably is worth it.

My fastest x86 system takes 6 seconds to boot from boot2 (no loader) to
mounting root.  Surprisingly, inittodr() runs even later than mountroot
(at least on an old system).  That must be for the old feature of
defaulting the time to a timestamp on the (ffs) root partition.  Normally
that is not used, but if inittodr() ran earlier than it would have to
run again if it couldn't find a hardware rtc.  Interrupt handling starts
working much earlier than that, but I wouldn't trust all time features
to be initialized on the first call to rtcintr().

However, it is unimportant to set the time very early in the boot.  This
just makes CLOCK_REALTIME timestamps valid earlier.

The time should be fixed up similarly after real suspensions.  Then it
is even less clear what the reinitialization order actually is.

>> Accuracy for reading is not very important because accuracy for
>> writing
>> is very low (1-2 seconds).  My resettodr() only writes if the
>> difference
>> is more than 2 seconds.
>>
>
> The gross inaccuracy when writing is fixable now.  I'm not worried
> about the microsecond inaccuracies of accessing the hardware, what I
> want to fix is the fact that clock_settime() may get called at x.995
> and will record the time as x.0.

Very old old versions seemed to have complications related to the
hardware.  Something to do with half-second boundaries, because the
hardware is "smart" about this 0.995 error and schedules the next
update to 0.5 seconds after writing to the seconds register (this
reduces the average error to 0.5 seconds for sloppy settings)?
I can't find these in the 2004 version.

> Because settime is now called from a task thread, any clock driver is
> free to sleep as needed to set the clock hardware in a way that aligns
> its second rollover with kernel time.  Not efficient, but easy to do.

The syscall was always free to sleep, and it is a bug for it return before
setting the time.  Except, the syscall never claimed to even have hardware
to write to.  If there were an RTC driver, then it should support both sync
and async settings.

> Even better, most rtc hardware has unused storage.  Sometimes in the
> form of battery-backed ram, sometimes in the form of things like alarm
> registers that aren't used for anything and a driver can tuck away
> values in them for its own use.  If clock_settime() stores the
> fractional part of the second in such a location, clock_gettime() can
> use it to remove all of the inaccuracy that otherwise happens when the
> fraction is discarded.  If even a single bit is available the error is
> cut in half.  If a byte is available it drops to ~40ms.

I tried to find unused rtc registers for the purpose of fixing nextboot
and other boot loaders which do dangerous writes to disks.  A single bit
is almost enough for them too.  I didn't really succeed.  On x86, everything
is reserved or undocumented and most of the 256 (?) bytes of standard cmos
was used by BIOSes before flash RAM made this unecessary (I don't know
how much of it they use now).  The best that I could find was the alarm
registers.  On some of my systems, the BIOS does use these registers, but
the use is under user control and when non-use by the BIOS is configured,
the BIOS doesn't clobber the registers.

Bruce


More information about the svn-src-all mailing list