* Re: rtc again...
@ 2000-08-08 11:35 Iain Sandoe
2000-08-08 13:14 ` Geert Uytterhoeven
0 siblings, 1 reply; 63+ messages in thread
From: Iain Sandoe @ 2000-08-08 11:35 UTC (permalink / raw)
To: Gabriel Paubert, Geert Uytterhoeven
Cc: benjamin herrenschmidt, martin costabel, linuxppc-dev
On Tue, Aug 8, 2000, Gabriel Paubert wrote:
> On Fri, 4 Aug 2000, Geert Uytterhoeven wrote:
>
>> > Actually given the problems with RTC being UTC or local time, the offset
>> > might perhaps better be setup as a kernel parameter so that th system
>> > start up in a known good state. It seems that it is in RAM for Macs, but
>> > what about other machines (I have no problems since all my machines are
>> > UTC and I simply refuse to use an OS which requires anything else) ?
>>
>> Why do you want to handle the offset in the kernel???
>>
>> Any decent distro (e.g. Debian) allows to configure the time system for a
>> hardware clock running in either UTC or local time, so the correction will be
>> done on boot up.
>>
>
> I think there is some misunderstanding here. I don't want to handle the
> offset in the kernel, with one possible exception: when reading the
> RTC for the first time to initialize xtime. Getting timestamps right as early
> as possible might be important in some cases, and it's not a big deal
> since the code to do this is small and thrown away anyway.
>
> Oh and I can't remember whether the clock or hwclock command ever worked
> on my machines. I think hwclock did once upon a time; life is so much
> simpler with NTP anyway (but it is run quite late in the boot process,
> actually just before the rc.local script on most of my machines and after
> mounting NFS file systems and starting daemons like syslogd/crond/inetd).
I seems to me (in summary) [since I started this thread :-) ]:
we can:
(a) Fix up time in the kernel to emulate UTC
(b) Fix up time in the kernel to emulates Local Time
Which (or will both) of these works with hwclock (since that is the
mechanism at 2.4.0 ?) and for those of us switching to-and-ffo is also
being used at 2.2.17
I would like to make sure that timestamps are right during kernel boot -
and, at the moment, when using 2.2.17 I have to 'artificially' disable rtc
to get the correct time.
For many (paid-by-the-call) telephone network users NTP is not a suitable
option - they don't like the machine making calls without asking.
Iain.
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 63+ messages in thread* Re: rtc again... 2000-08-08 11:35 rtc again Iain Sandoe @ 2000-08-08 13:14 ` Geert Uytterhoeven 0 siblings, 0 replies; 63+ messages in thread From: Geert Uytterhoeven @ 2000-08-08 13:14 UTC (permalink / raw) To: Iain Sandoe Cc: Gabriel Paubert, benjamin herrenschmidt, martin costabel, linuxppc-dev On Tue, 8 Aug 2000, Iain Sandoe wrote: > I seems to me (in summary) [since I started this thread :-) ]: > > we can: > > (a) Fix up time in the kernel to emulate UTC > (b) Fix up time in the kernel to emulates Local Time Please also think about people who really run their RTC in UTC, who don't run MacOS anymore, or who simply don't have a PowerMac. > Which (or will both) of these works with hwclock (since that is the > mechanism at 2.4.0 ?) and for those of us switching to-and-ffo is also > being used at 2.2.17 Hwclock is userspace. It depends on the distro. Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again...
@ 2000-08-08 14:31 Iain Sandoe
2000-08-08 17:08 ` Michael Schmitz
0 siblings, 1 reply; 63+ messages in thread
From: Iain Sandoe @ 2000-08-08 14:31 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Gabriel Paubert, benjamin herrenschmidt, martin costabel,
linuxppc-dev
On Tue, Aug 8, 2000, Geert Uytterhoeven wrote:
> On Tue, 8 Aug 2000, Iain Sandoe wrote:
>> I seems to me (in summary) [since I started this thread :-) ]:
>>
>> we can:
>>
>> (a) Fix up time in the kernel to emulate UTC
>> (b) Fix up time in the kernel to emulates Local Time
>
> Please also think about people who really run their RTC in UTC, who don't run
> MacOS anymore, or who simply don't have a PowerMac.
It was never my intention to suggest otherwise - as (I'm sure) I'm on record
as saying - I've used all of 'em and have no particular favourites or axe to
grind :-)
I *would* like a working solution for those of us whose machines include
pmac and still need MacOS for some jobs.
Iain.
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 63+ messages in thread* Re: rtc again... 2000-08-08 14:31 Iain Sandoe @ 2000-08-08 17:08 ` Michael Schmitz 2000-08-08 17:41 ` Benjamin Herrenschmidt 0 siblings, 1 reply; 63+ messages in thread From: Michael Schmitz @ 2000-08-08 17:08 UTC (permalink / raw) To: Iain Sandoe Cc: Geert Uytterhoeven, Gabriel Paubert, benjamin herrenschmidt, martin costabel, linuxppc-dev > >> (a) Fix up time in the kernel to emulate UTC > >> (b) Fix up time in the kernel to emulates Local Time > > > > Please also think about people who really run their RTC in UTC, who don't run > > MacOS anymore, or who simply don't have a PowerMac. > > It was never my intention to suggest otherwise - as (I'm sure) I'm on record > as saying - I've used all of 'em and have no particular favourites or axe to > grind :-) > > I *would* like a working solution for those of us whose machines include > pmac and still need MacOS for some jobs. So what about setting the kernel internal time to local time including all fixups at least on Powermacs (using the data passed by OF or read from NVRAM) and to UTC (or more precisely, whatever the RTC is set to) on all those where we cannot determine UTC and DST offsets from OF or NVRAM? Next, agree on either returning local time or UTC, at any rate a time without accounting for GMT and DST offset, via /dev/rtc so user space tools won't notice a difference ? I'd vote for UTC format for /dev/rtc. We do assume the user set up the clock properly (as in: actually bothered to set the clock to UTC and define GMT and DST offset as apparently done by the MacOS Date&Time control panel), and set hwclock to interpret the time as UTC. Or the user set up the clock in local time (no DST offset) and set hwclock to interpret the time as local time. This way - early log stamps and later ones agree on all those machines that let the kernel figure out GMT and DST offset, and are off by at most the DST offset if the clock is set to local time, - we don't need any special case handling in hwclock. Impossible? Michael ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-08 17:08 ` Michael Schmitz @ 2000-08-08 17:41 ` Benjamin Herrenschmidt 2000-08-08 22:44 ` Gabriel Paubert ` (2 more replies) 0 siblings, 3 replies; 63+ messages in thread From: Benjamin Herrenschmidt @ 2000-08-08 17:41 UTC (permalink / raw) To: Michael Schmitz, linuxppc-dev > >So what about setting the kernel internal time to local time including all >fixups at least on Powermacs (using the data passed by OF or read from >NVRAM) and to UTC (or more precisely, whatever the RTC is set to) on all >those where we cannot determine UTC and DST offsets from OF or NVRAM? >Next, agree on either returning local time or UTC, at any rate a time >without accounting for GMT and DST offset, via /dev/rtc so user space >tools won't notice a difference ? I'd vote for UTC format for /dev/rtc. I'm against changing the kernel time to something different on some machines than on others. Let's resume my understanding of things: The kernel keeps two things: - xtime is the current time and should be UTC. - sys_tz is the current timezone (usually set from userland) When the kernel boots, it reads the time from the RTC. On pmac (or any other machine that has a local time), that means that the kernel boots with a wrong notion of time until that gets fixed from userland. That's why I added that code that calculates the real UTC from the xpram. It also initialize properly the sys_tz structure, since it's easy, doesn't cost much, and I think it's always better to have a correct value when we can ;) This would also allow some tools and/or installers to "read" the timezone at boot in order to propose a default choice or such things. Now there are several problems: - The first one, well hidden in kernel/time.c (generic code) is the call to warp_time(). This is an awful hack that seem to be done because PCs apparently also set the RTC to local time. This hack will cause the kernel to "bump" the xtime the first time the syscall settimeofday() is called is it is called with a valid timezone and a NULL timevalue. With old broken behaviour, this code has the effect of causing the kernel to "adjust" it's internal time that was wrongly set to local time to be real UTC as soon as it is notified by userland of the real time zone. Obviously, this code breaks us. We should probably change it so that a global variables tells this code we have already inited sys_tz properly and there's no need to warp. - The second one is that ppc_md.get/set_rtc_time are passed (or return) a time value independently of the timezone. That mean that they either do no conversion and so it's the responsibility of the caller to "know" if the RTC is in local time or UTC, or they do the conversion and so return (and get passed) an UTC time. That's what I decided to do, so on PowerMac, they do the adjustement from UTC to localtime and the opposite inside those functions. Paul recently added code to also save the timezone to the xpram. There's a small semantic problem with this code, since it takes the time to set to the RTC as a parameter but uses the global sys_tz. It should either use no parameter (and use only xtime/ sys_tz), or be passed both parameters. In this case, we can probably move the init code that reads the initial time zone to the pmac_get_rtc_time() too. - There's apparently a problem with the definition of the DST field of sys_tz. The best way to handle this correctly is probably to see how userland tools like hwclock use it. What is responsible for managing DST on linux ? Is there a deamon for that ? A tool called from cron ? ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-08 17:41 ` Benjamin Herrenschmidt @ 2000-08-08 22:44 ` Gabriel Paubert 2000-08-09 8:44 ` Benjamin Herrenschmidt 2000-08-09 0:55 ` Takashi Oe 2000-08-09 14:24 ` Geert Uytterhoeven 2 siblings, 1 reply; 63+ messages in thread From: Gabriel Paubert @ 2000-08-08 22:44 UTC (permalink / raw) To: Benjamin Herrenschmidt; +Cc: Michael Schmitz, linuxppc-dev On Tue, 8 Aug 2000, Benjamin Herrenschmidt wrote: > The kernel keeps two things: > > - xtime is the current time and should be UTC. ^^^^^^ must > - sys_tz is the current timezone (usually set from userland) Indeed, and it is used mostly (only?) by some filesystems which keep time in local time. > When the kernel boots, it reads the time from the RTC. On pmac (or any > other machine that has a local time), that means that the kernel boots > with a wrong notion of time until that gets fixed from userland. > > That's why I added that code that calculates the real UTC from the xpram. > It also initialize properly the sys_tz structure, since it's easy, > doesn't cost much, and I think it's always better to have a correct value > when we can ;) This would also allow some tools and/or installers to > "read" the timezone at boot in order to propose a default choice or such > things. > > Now there are several problems: > > - The first one, well hidden in kernel/time.c (generic code) is the call > to warp_time(). This is an awful hack that seem to be done because PCs > apparently also set the RTC to local time. This is necessary for people who dual boot some M$ stuff (my PC is UTC and it just works fine). > This hack will cause the > kernel to "bump" the xtime the first time the syscall settimeofday() is > called is it is called with a valid timezone and a NULL timevalue. > With old broken behaviour, this code has the effect of causing the kernel > to "adjust" it's internal time that was wrongly set to local time to be > real UTC as soon as it is notified by userland of the real time zone. > Obviously, this code breaks us. We should probably change it so that a > global variables tells this code we have already inited sys_tz properly > and there's no need to warp. You could also call do_sys_settimeofday with correct tz from pram and a null tv to adjust xtime and prevent userland from messing with it again (faking the first call used to set timezone). do_sys_settimeofday is a public symbol since it's used by sparc and alpha code (at least) for some OSF and SunOS emulation. Pushing this timezone setting policy to architecture dependant code is another possibility, but the changes are bigger. > - The second one is that ppc_md.get/set_rtc_time are passed (or return) > a time value independently of the timezone. That mean that they either do > no conversion and so it's the responsibility of the caller to "know" if > the RTC is in local time or UTC, or they do the conversion and so return > (and get passed) an UTC time. That's what I decided to do, so on > PowerMac, they do the adjustement from UTC to localtime and the opposite > inside those functions. Paul recently added code to also save the > timezone to the xpram. There's a small semantic problem with this code, > since it takes the time to set to the RTC as a parameter but uses the > global sys_tz. It should either use no parameter (and use only xtime/ > sys_tz), or be passed both parameters. In this case, we can probably move > the init code that reads the initial time zone to the pmac_get_rtc_time() too. I'm slightly lost :-(. But whether the clock is in UTC or not is a parameter (defined in /etc/sysconfig/clock or another system configuration file), so I think that translating to/from UTC when setting the clock is a purely userland job and set/get_rtc_time should never have to handle this. > > - There's apparently a problem with the definition of the DST field of > sys_tz. The best way to handle this correctly is probably to see how > userland tools like hwclock use it. What is responsible for managing DST > on linux ? Is there a deamon for that ? A tool called from cron ? No, AFAICT nothing bothers with it, only the clock program at boot. First it is 99% a userland problem: just set export TZ=UTC or any path in /usr/share/zoneinfo and all dates will appear as if you were in this timezone (try date or ls -l). The translation between UTC and localtime is performed in the C library, using the TZ environment variable or /etc/localtime, and it will know when to switch between DST and non DST. The last problem is updating the clock through NTP when the RTC is running in local time. Since these are generally small corrections, there are solutions (but the comments of the i386 version say that it is buggy :-(). Until now I've found a single place where sys_tz.dsttime is used in the kernel: fs/fat/misc.c when converting between Unix and FAT timestamps. Interestingly it's used only in one direction, so it definitely looks like a bug. Some other filesystems (affs/hfs/ncpfs/ufs) use the timezone information but not the dst field, making FAT time handling look even buggier. Regards, Gabriel. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-08 22:44 ` Gabriel Paubert @ 2000-08-09 8:44 ` Benjamin Herrenschmidt 2000-08-09 11:32 ` Martin Costabel ` (2 more replies) 0 siblings, 3 replies; 63+ messages in thread From: Benjamin Herrenschmidt @ 2000-08-09 8:44 UTC (permalink / raw) To: Gabriel Paubert, linuxppc-dev > >I'm slightly lost :-(. But whether the clock is in UTC or not is a >parameter (defined in /etc/sysconfig/clock or another system configuration >file), so I think that translating to/from UTC when setting the clock is a >purely userland job and set/get_rtc_time should never have to handle this. The problem is that those functions are in-kernel, and without proper conversion, they could put incorrect time in the RTC. Those are called by /dev/rtc on macintosh, additionally, get_rtc_time() is called at boot, and set_rtc_time() used to be called regulary (the famous code I #if'ed out). So if it's a userland-only thing, then the set_time() must be removed since the kernel can't know if the RTC is UTC or local time. Except if we decide that on PowerMac, we always follow Apple layout (to be compatible with MacOS X) and implement the UTC/local conversion inside those so they always expose UTC times to the kernel. >No, AFAICT nothing bothers with it, only the clock program at boot. And the fat file system (see below) >First it is 99% a userland problem: just set export TZ=UTC or any path in >/usr/share/zoneinfo and all dates will appear as if you were in this >timezone (try date or ls -l). > >The translation between UTC and localtime is performed in the C library, >using the TZ environment variable or /etc/localtime, and it will know when >to switch between DST and non DST. > >The last problem is updating the clock through NTP when the RTC is running >in local time. Since these are generally small corrections, there are >solutions (but the comments of the i386 version say that it is buggy :-(). I see no solution to this problem but do the conversion in kernel. Also, whatever userland does after boot, it's nice to have a correct time and timezone as early as possible, especialy if it takes only a few lines of kernel code to grab the correct MacOS values. I don't see why we shouldn't have those in-kernel get/set time do the conversion, at least on pmac. I see no point of trying to mimmic the PC behaviour here. The Mac clock is supposed to run local time, but we do have the timezone info in a known location in pram, I see no reason to let users (on pmac at least) store UTC in the RTC. CHRP/PReP are a different matter. Now, I need to check how this interracts with our pmac /dev/rtc so that userland "see" a consistent kernel interface. This new /dev/rtc driver means userland will go thry the ppc_md.set/get time functions when using this driver (the old "clock" program used to directly talk to Cuda/PMU via /dev/adb, I wanted to get rid of that). >Until now I've found a single place where sys_tz.dsttime is used in the >kernel: fs/fat/misc.c when converting between Unix and FAT timestamps. >Interestingly it's used only in one direction, so it definitely looks like >a bug. Some other filesystems (affs/hfs/ncpfs/ufs) use the timezone >information but not the dst field, making FAT time handling look even >buggier. Yep. My understanding (and that's also how MacOS uses it) is that the DST correction is _included_ in the timezone offset, the dst field beeing just an indication. So yes, FAT is probably broken. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-09 8:44 ` Benjamin Herrenschmidt @ 2000-08-09 11:32 ` Martin Costabel 2000-08-09 13:50 ` Gabriel Paubert 2000-08-09 14:26 ` Takashi Oe 2 siblings, 0 replies; 63+ messages in thread From: Martin Costabel @ 2000-08-09 11:32 UTC (permalink / raw) To: Benjamin Herrenschmidt; +Cc: Gabriel Paubert, linuxppc-dev Benjamin Herrenschmidt wrote: > > > > >I'm slightly lost :-(. But whether the clock is in UTC or not is a > >parameter (defined in /etc/sysconfig/clock or another system configuration > >file), so I think that translating to/from UTC when setting the clock is a > >purely userland job and set/get_rtc_time should never have to handle this. > > The problem is that those functions are in-kernel, and without proper > conversion, they could put incorrect time in the RTC. Those are called by > /dev/rtc on macintosh, additionally, get_rtc_time() is called at boot, > and set_rtc_time() used to be called regulary (the famous code I #if'ed out). > > So if it's a userland-only thing, then the set_time() must be removed > since the kernel can't know if the RTC is UTC or local time. Except if we > decide that on PowerMac, we always follow Apple layout (to be compatible > with MacOS X) and implement the UTC/local conversion inside those so they > always expose UTC times to the kernel. Do I understand this right: As a Pmac user, I have to set "UTC=yes" in /etc/sysconfig/clock, and then everything will be working correctly? So only those developers who want to lose their sanity by trying to hack the kernel time routines have to know that the Pmac CMOS clock is actually running in localtime, whereas for everyone else, kernel and userland, it appears to run in UTC? This makes sense. It also explains the recent confusion: I think I used to have UTC=yes, until with the recent introduction of rtc.c, everyone was claiming that the Pmac CMOS clock runs in localtime, so I switched to UTC=false. It would be nice to have the same system in all the kernel trees. Right now, the 5 kernel trees at penguinppc.org have 4 different versions of the {s|g}et_rtc_time() routines in arch/ppc/kernel/pmac_time.c. In the bitkeeper-devel kernel, these 2 routines aren't even compatible: If you say "hwclock --systohc" and then "hwclock --hctosys", you don't get the same time as before. <2 reboots later> This is driving me nuts! What I wrote above worked nicely for a bitkeeper-2.2.17 kernel with arch/ppc/kernel/pmac_time.c from pmac-benh. I now tried it with a pmac-devel 2.4.0-test6 kernel which has the same logic of offsets get_rtc_time() in pmac_time.c, if I am able to read. But it does not give the same result! System time is off by 2 hours. So this kernel wants "UTC=false"... And I am back to square one: Impossible to configure my system using RTC and the new hwclock in such a way that a 2.2.17 kernel and a 2.4.0 kernel boot up to the same system time. </giving up> -- Martin ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-09 8:44 ` Benjamin Herrenschmidt 2000-08-09 11:32 ` Martin Costabel @ 2000-08-09 13:50 ` Gabriel Paubert 2000-08-09 15:25 ` Benjamin Herrenschmidt 2000-08-09 14:26 ` Takashi Oe 2 siblings, 1 reply; 63+ messages in thread From: Gabriel Paubert @ 2000-08-09 13:50 UTC (permalink / raw) To: Benjamin Herrenschmidt; +Cc: linuxppc-dev On Wed, 9 Aug 2000, Benjamin Herrenschmidt wrote: > > > >I'm slightly lost :-(. But whether the clock is in UTC or not is a > >parameter (defined in /etc/sysconfig/clock or another system configuration > >file), so I think that translating to/from UTC when setting the clock is a > >purely userland job and set/get_rtc_time should never have to handle this. > > The problem is that those functions are in-kernel, and without proper > conversion, they could put incorrect time in the RTC. Those are called by > /dev/rtc on macintosh, additionally, get_rtc_time() is called at boot, > and set_rtc_time() used to be called regulary (the famous code I #if'ed out). No, the code was wrong, it should only be called if the kernel PLL is running, i.e. if STA_UNSYNC is 0. Since STA_UNSYNC is set at boot, it should never be called by default. And this code should also only track small drifts, i.e., only set the minutes and seconds for NTP. > So if it's a userland-only thing, then the set_time() must be removed > since the kernel can't know if the RTC is UTC or local time. Except if we > decide that on PowerMac, we always follow Apple layout (to be compatible > with MacOS X) and implement the UTC/local conversion inside those so they > always expose UTC times to the kernel. > > >No, AFAICT nothing bothers with it, only the clock program at boot. > > And the fat file system (see below) Some other file systems bother with the the zone too, and that one is only set on every reboot on your average Linux machine... > > >First it is 99% a userland problem: just set export TZ=UTC or any path in > >/usr/share/zoneinfo and all dates will appear as if you were in this > >timezone (try date or ls -l). > > > >The translation between UTC and localtime is performed in the C library, > >using the TZ environment variable or /etc/localtime, and it will know when > >to switch between DST and non DST. > > > >The last problem is updating the clock through NTP when the RTC is running > >in local time. Since these are generally small corrections, there are > >solutions (but the comments of the i386 version say that it is buggy :-(). > > I see no solution to this problem but do the conversion in kernel. Also, > whatever userland does after boot, it's nice to have a correct time and > timezone as early as possible, especialy if it takes only a few lines of > kernel code to grab the correct MacOS values. I agree on the point if setting the timezone at boot, that's basically the only thing I would consider permissible. For the rest the RTC is running as is, and /dev/rtc gives you direct acces to the HW: no cooked values, you always end up losing when playing such games. > I don't see why we shouldn't have those in-kernel get/set time do the > conversion, at least on pmac. I see no point of trying to mimmic the PC > behaviour here. I do see some: principle of least surprise for people porting applications between PC and Mac. Minimize #ifdef noise in their sources... > The Mac clock is supposed to run local time, but we do > have the timezone info in a known location in pram, I see no reason to > let users (on pmac at least) store UTC in the RTC. CHRP/PReP are a > different matter. I happen to disagree, it depends on what will happen with MacOS and the schizophreny of having timezone parameters in the NVRAM and in the OS config. I don't know MacOS so I might be wrong, but there might be a solution running if MacOS does things in a sensible way (preferences override RAM settings, which is the right thing to do when you are travelling around the world with your notebook, and also if you have to zap the RAM for some reason): During Linux boot: read the time and offset from xpram and set xtime accordingly (preventing further timewarps by using do_sys_settimofday), then clear the timezone info in the RAM, and rewrite the clock so that it runs in UTC. Under MacOS: use MacOS preferences to set the timezone at least once, hopefully when it boots it will either a) leave the RTC as is (making it work properly as an UTC clock), or b) warp the clock and save the offsets in RAM. Yes, this is strange, but the original error lies with Apple storing the time as local time while keeping also the timezone. I can understand and even agree on keeping the timezone and the DST flag in RAM, but then why the heck do you want to store the RTC in local time ? It only makes thing more complex around DST changes or when changing timezones when you travel. I thought Macs were about simplicity... > Now, I need to check how this interracts with our pmac /dev/rtc so that > userland "see" a consistent kernel interface. This new /dev/rtc driver > means userland will go thry the ppc_md.set/get time functions when using > this driver (the old "clock" program used to directly talk to Cuda/PMU > via /dev/adb, I wanted to get rid of that). > > >Until now I've found a single place where sys_tz.dsttime is used in the > >kernel: fs/fat/misc.c when converting between Unix and FAT timestamps. > >Interestingly it's used only in one direction, so it definitely looks like > >a bug. Some other filesystems (affs/hfs/ncpfs/ufs) use the timezone > >information but not the dst field, making FAT time handling look even > >buggier. > > Yep. My understanding (and that's also how MacOS uses it) is that the DST > correction is _included_ in the timezone offset, the dst field beeing > just an indication. So yes, FAT is probably broken. Who uses FAT anyway ? I'm going to patch my kernels to kill sys_tz, now that I've come to the conclusion that its mere existence is an aberration... With an UTC clock, it's the only sensible solution ;-). But I don't suggest that everybody should do the same... Regards, Gabriel ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-09 13:50 ` Gabriel Paubert @ 2000-08-09 15:25 ` Benjamin Herrenschmidt 2000-08-09 16:54 ` Takashi Oe 2000-08-09 22:13 ` Gabriel Paubert 0 siblings, 2 replies; 63+ messages in thread From: Benjamin Herrenschmidt @ 2000-08-09 15:25 UTC (permalink / raw) To: Gabriel Paubert, linuxppc-dev > >I agree on the point if setting the timezone at boot, that's basically the >only thing I would consider permissible. For the rest the RTC is running >as is, and /dev/rtc gives you direct acces to the HW: no cooked values, >you always end up losing when playing such games. Ok. Then for this to work, we need to slightly change the boot code not to call simply ppc_md.get_rtc_time(), but to also adjust it on pmac using the pram timezone. That means adding a new ppc_md.fixup_time() used only at boot, or adding a "fixup" parameter to ppc_mc.get_rtc_time() set to 0 in normal cases and to 1 on first call during boot. >I do see some: principle of least surprise for people porting applications >between PC and Mac. Minimize #ifdef noise in their sources... Well, it's nice to save back the timezone to the xpram (the code Paul added). But it's probably not good to do so from ppc_md.set_rtc_time(). So that would yet another #if/_MACH_Pmac hack... >During Linux boot: read the time and offset from xpram and set xtime >accordingly (preventing further timewarps by using do_sys_settimofday), >then clear the timezone info in the RAM, and rewrite the clock so that it >runs in UTC. Clear the tz info in nvram ? why ? That would probably harm MacOS... And I don't like writing to nvram when it's not necessary (nvram is a flash on some machines). I would rather let the RTC run in local time and pass localtime to userland, letting the user set the userland tool correctly and so behave like other archs with local time RTC. So to resume, what I need to fix is: - change ppc_md.get/set_rtc_time() to set and return the raw time from the RTC - at boot, apply only once the offset from nvram, initialize sys_tz and call do_sys_settimeofday() - Figure out a way to write back the timezone to nvram (since I think sys_tz is updated by userland tools via settimeofday, isn't it ?) when changed. >Yes, this is strange, but the original error lies with Apple storing the >time as local time while keeping also the timezone. I can understand and >even agree on keeping the timezone and the DST flag in RAM, but then why >the heck do you want to store the RTC in local time ? It only makes thing >more complex around DST changes or when changing timezones when you >travel. I thought Macs were about simplicity... Macs are about simplicity, MacOS internals are not ;) >Who uses FAT anyway ? I'm going to patch my kernels to kill sys_tz, now >that I've come to the conclusion that its mere existence is an >aberration... With an UTC clock, it's the only sensible solution ;-). But >I don't suggest that everybody should do the same... Hum... ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-09 15:25 ` Benjamin Herrenschmidt @ 2000-08-09 16:54 ` Takashi Oe 2000-08-09 17:04 ` Benjamin Herrenschmidt 2000-08-09 22:13 ` Gabriel Paubert 1 sibling, 1 reply; 63+ messages in thread From: Takashi Oe @ 2000-08-09 16:54 UTC (permalink / raw) To: Benjamin Herrenschmidt; +Cc: Gabriel Paubert, linuxppc-dev On Wed, 9 Aug 2000, Benjamin Herrenschmidt wrote: > Ok. Then for this to work, we need to slightly change the boot code not > to call simply ppc_md.get_rtc_time(), but to also adjust it on pmac using > the pram timezone. That means adding a new ppc_md.fixup_time() used only > at boot, or adding a "fixup" parameter to ppc_mc.get_rtc_time() set to 0 > in normal cases and to 1 on first call during boot. Or let ppc_md.time_init() return offset between ppc_md.get_rtc_time() value and UTC and use the offset in time_init() as I proposed previously... Takashi Oe ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-09 16:54 ` Takashi Oe @ 2000-08-09 17:04 ` Benjamin Herrenschmidt 2000-08-09 23:12 ` Takashi Oe 0 siblings, 1 reply; 63+ messages in thread From: Benjamin Herrenschmidt @ 2000-08-09 17:04 UTC (permalink / raw) To: Takashi Oe, linuxppc-dev >> Ok. Then for this to work, we need to slightly change the boot code not >> to call simply ppc_md.get_rtc_time(), but to also adjust it on pmac using >> the pram timezone. That means adding a new ppc_md.fixup_time() used only >> at boot, or adding a "fixup" parameter to ppc_mc.get_rtc_time() set to 0 >> in normal cases and to 1 on first call during boot. > >Or let ppc_md.time_init() return offset between ppc_md.get_rtc_time() >value and UTC and use the offset in time_init() as I proposed >previously... Yes, that would work. But when the offset is non-NULL we must also make sure we call do_settimeofday() to disable the warp hack in kernel/time.c Saving the timezone value to xpram is another issue. It could be done from userland but we currently don't have userland tool that properly access the xpram portion of the nvram. I did plan to add some ioctls to / dev/nvram for it to return the location of the various nvram partitions, looks like it will be time to actually implement them... Also, the userland tool will have to be written... ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-09 17:04 ` Benjamin Herrenschmidt @ 2000-08-09 23:12 ` Takashi Oe 2000-08-09 23:48 ` Benjamin Herrenschmidt 0 siblings, 1 reply; 63+ messages in thread From: Takashi Oe @ 2000-08-09 23:12 UTC (permalink / raw) To: Benjamin Herrenschmidt; +Cc: linuxppc-dev On Wed, 9 Aug 2000, Benjamin Herrenschmidt wrote: > Saving the timezone value to xpram is another issue. It could be done > from userland but we currently don't have userland tool that properly > access the xpram portion of the nvram. I did plan to add some ioctls to / > dev/nvram for it to return the location of the various nvram partitions, > looks like it will be time to actually implement them... Also, the > userland tool will have to be written... I had a xpram manipulation tool, so I modified it a bit. Also, I added an ioctl to drivers/macintosh/nvram.c. Please have a look at them. Are these what you had in mind? Takashi Oe Kernel mods: --- linux-2.4.0-test4/include/asm-ppc/nvram.h Tue May 2 15:05:40 2000 +++ linux-nubus/include/asm-ppc/nvram.h Wed Aug 9 17:44:23 2000 @@ -38,12 +38,14 @@ pmac_nvram_NR /* MacOS Name Registry partition */ }; +#ifdef __KERNEL__ /* Return partition offset in nvram */ extern int pmac_get_partition(int partition); /* Direct access to XPRAM */ extern u8 pmac_xpram_read(int xpaddr); extern void pmac_xpram_write(int xpaddr, u8 data); +#endif /* __KERNEL__ */ /* Some offsets in XPRAM */ #define PMAC_XPRAM_MACHINE_LOC 0xe4 @@ -51,9 +53,12 @@ /* Machine location structure in XPRAM */ struct pmac_machine_location { - u32 latitude; /* 2+30 bit Fractional number */ - u32 longitude; /* 2+30 bit Fractional number */ - u32 delta; /* mix of GMT delta and DLS */ + unsigned int latitude; /* 2+30 bit Fractional number */ + unsigned int longitude; /* 2+30 bit Fractional number */ + unsigned int delta; /* mix of GMT delta and DLS */ }; + +/* /dev/nvram ioctls */ +#define PMAC_NVRAM_GET_OFFSET _IOWR('p', 0x40, int) /* Get NVRAM partition offset */ #endif --- linux-2.4.0-test4/drivers/macintosh/nvram.c Tue Jun 20 15:58:42 2000 +++ linux-nubus/drivers/macintosh/nvram.c Wed Aug 9 16:44:50 2000 @@ -14,6 +14,7 @@ #include <linux/nvram.h> #include <linux/init.h> #include <asm/uaccess.h> +#include <asm/nvram.h> #define NVRAM_SIZE 8192 @@ -70,11 +71,36 @@ return p - buf; } +static int nvram_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + switch(cmd) { + case PMAC_NVRAM_GET_OFFSET: + { + int part, offset; + if (copy_from_user(&part,(void*)arg,sizeof(part))!=0) + return -EFAULT; + if (part < pmac_nvram_OF || part > pmac_nvram_NR) + return -EINVAL; + offset = pmac_get_partition(part); + if (copy_to_user((void*)arg,&offset,sizeof(offset))!=0) + return -EFAULT; + break; + } + + default: + return -EINVAL; + } + + return 0; +} + struct file_operations nvram_fops = { owner: THIS_MODULE, llseek: nvram_llseek, read: read_nvram, write: write_nvram, + ioctl: nvram_ioctl, }; static struct miscdevice nvram_dev = { Userland utilitity: xpram.c #include <stdio.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <unistd.h> #include <time.h> #include <fcntl.h> #include <getopt.h> #include <sys/ioctl.h> #include <asm/nvram.h> /* Globals */ int set_timezone = 0; void usage (char *str) { fprintf (stderr, "%s offset [val]\n" "%s -t\n" " t: update XPRAM timezone info\n", str, str); exit(EXIT_FAILURE); } int nvram_fd; static void nvram_init ( int rw_flag ) { if (rw_flag && getuid () != 0) { fprintf (stderr, "Sorry, must be root to set XPRAM value\n"); exit(EXIT_FAILURE); } nvram_fd = open ("/dev/nvram", rw_flag? O_RDWR: O_RDONLY); if (nvram_fd < 0) { fprintf (stderr, "unable to open /dev/nvram read/write : %s\n", rw_flag? "read/write": "read only", strerror(errno)); exit(EXIT_FAILURE); } } int main (int argc, char **argv ) { int i, arg, rw = 0; unsigned long address; unsigned char val; char *p; extern int optind; while ((arg = getopt (argc, argv, "t")) != -1) { switch (arg) { case 't': set_timezone = 1; break; default: usage (argv[0]); } } if (set_timezone) { address = PMAC_XPRAM_MACHINE_LOC; rw = 1; } else { if (!argv[optind]) usage(argv[0]); address = strtoul(argv[optind], &p, 0); if (p == argv[optind]) usage(argv[0]); if (argv[++optind]) { val = (unsigned char)strtoul(argv[optind], &p, 0); if (p == argv[optind]) usage(argv[0]); rw = 1; } } nvram_init (rw); i = pmac_nvram_XPRAM; if (ioctl(nvram_fd, PMAC_NVRAM_GET_OFFSET, &i) < 0) { fprintf(stderr, "ioctl PMAC_NVRAM_GET_OFFSET: %s\n", strerror(errno)); exit(EXIT_FAILURE); } address += i; if (set_timezone) { unsigned char buf[4]; time_t gmt; int utc_offset; gmt = time( NULL ); (void )localtime( &gmt ); utc_offset = -timezone + (daylight? 3600: 0); if (lseek(nvram_fd, address + 8, 0) < 0 || read(nvram_fd, buf, 1) != 1) { fprintf(stderr, "Error reading from /dev/nvram: %s", strerror(errno)); exit(EXIT_FAILURE); } buf[0] = (buf[0] & 0x7f) | ((daylight)? 0x80: 0); buf[1] = ((unsigned)(utc_offset) >> 16) & 0xff; buf[2] = ((unsigned)(utc_offset) >> 8) & 0xff; buf[3] = (unsigned)(utc_offset) & 0xff; if (lseek(nvram_fd, address + 8, 0) < 0 || write(nvram_fd, buf, 4) != 4) { fprintf(stderr, "Error writing to /dev/nvram: %s", strerror(errno)); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); } if (!rw) { if (lseek(nvram_fd, address, 0) < 0 || read(nvram_fd, &val, 1) != 1) { fprintf(stderr, "Error reading from /dev/nvram: %s", strerror(errno)); exit(EXIT_FAILURE); } printf("0x%02X\n", val); } else { if (lseek(nvram_fd, address, 0) < 0 || write(nvram_fd, &val, 1) != 1) { fprintf(stderr, "Error writing to /dev/nvram: %s", strerror(errno)); exit(EXIT_FAILURE); } } exit(EXIT_SUCCESS); } ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-09 23:12 ` Takashi Oe @ 2000-08-09 23:48 ` Benjamin Herrenschmidt 0 siblings, 0 replies; 63+ messages in thread From: Benjamin Herrenschmidt @ 2000-08-09 23:48 UTC (permalink / raw) To: Takashi Oe, linuxppc-dev >> Saving the timezone value to xpram is another issue. It could be done >> from userland but we currently don't have userland tool that properly >> access the xpram portion of the nvram. I did plan to add some ioctls to / >> dev/nvram for it to return the location of the various nvram partitions, >> looks like it will be time to actually implement them... Also, the >> userland tool will have to be written... > >I had a xpram manipulation tool, so I modified it a bit. Also, I added an >ioctl to drivers/macintosh/nvram.c. > >Please have a look at them. Are these what you had in mind? Ah, sometimes I'd like to have more often access to my linux boxes ;) Looks nice, I'll test that asap (probably sometimes this week-end) and push along with the other fixes. Ben. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-09 15:25 ` Benjamin Herrenschmidt 2000-08-09 16:54 ` Takashi Oe @ 2000-08-09 22:13 ` Gabriel Paubert 2000-08-09 22:48 ` Benjamin Herrenschmidt 2000-08-10 0:00 ` William Blew 1 sibling, 2 replies; 63+ messages in thread From: Gabriel Paubert @ 2000-08-09 22:13 UTC (permalink / raw) To: Benjamin Herrenschmidt; +Cc: linuxppc-dev On Wed, 9 Aug 2000, Benjamin Herrenschmidt wrote: > > > >I agree on the point if setting the timezone at boot, that's basically the > >only thing I would consider permissible. For the rest the RTC is running > >as is, and /dev/rtc gives you direct acces to the HW: no cooked values, > >you always end up losing when playing such games. > > Ok. Then for this to work, we need to slightly change the boot code not > to call simply ppc_md.get_rtc_time(), but to also adjust it on pmac using > the pram timezone. That means adding a new ppc_md.fixup_time() used only > at boot, or adding a "fixup" parameter to ppc_mc.get_rtc_time() set to 0 > in normal cases and to 1 on first call during boot. I strongly suspect that we might want a single rtc access function in ppc_md and add a first parameter telling what we want it to do, the second being a pointer to a tv_sec, and perhaps more parameters. I have problems for example with repeatability of boot-time timebase frequency measurements (yes 2-3 ppm are extremely important for me) which could be solved by yet another entry in ppc_md but I don't want it. The solution would be to read the rtc and return the timebase value at the time the second changes. This ppc_md.rtc_access should provide the following functions or something equivalent, PPC_RTC_READ_TIME, PPC_RTC_WRITE_TIME, PPC_RTC_WRITE_MMSS (for NTP/adjtime adjustments), PPC_RTC_CALIBRATE_TB (needed for some machines, measure as precisely as possible the timebase difference between 2 second transitions, this means on PreP for example setting the NVRAM pointer to the seconds byte and repeatedly reading it instead of rereading the whole year to seconds every time), This last function could also be performed by returning the timebase in the READ_TIME function as an extra parameter. The best solution is the one which gives the minimal permanent kernel size, __init code size is irrelevant. > >I do see some: principle of least surprise for people porting applications > >between PC and Mac. Minimize #ifdef noise in their sources... > > Well, it's nice to save back the timezone to the xpram (the code Paul > added). But it's probably not good to do so from ppc_md.set_rtc_time(). > So that would yet another #if/_MACH_Pmac hack... What use does it have if no daemon will change the timezone anyway ? Your time offset will be updated on the fly (at least for newly forked processes), but the kernel sys_tz won't. This might actually be construed as a feature, imagine running make in a filesystem with local time filestamps around a backward DST change... AFAICT for example Win98 will change the RTC only on reboot when it detects that the DST setting has changed since last reboot. And even that does not work properly (that's what a colleague told me, so take it with a grain of salt). This maybe because time warps would confuse running (M$ of course) applications, and anyway you are not supposed to leave it running overnight, it will anyway crash for you if you forget to shutdown ;-) How does MacOS handle DST changes (on the fly or only at reboot) ? > Clear the tz info in nvram ? why ? That would probably harm MacOS... And > I don't like writing to nvram when it's not necessary (nvram is a flash > on some machines). I would rather let the RTC run in local time and pass > localtime to userland, letting the user set the userland tool correctly You never (well hardldy ever) pass localtime to userland in Unix and that's a big big big plus, each process/user can set TZ as it wishes. IOW the value of sys_tz is at best a system wide default but is not imposed to anybody. Here at the telescope on all Linux machines, /etc/localtime is set as UTC, but then I set TZ=Europe/Madrid in my .profile to avoid too much confusion with my PC which has localtime set to Europe/Madrid. And right now I am running a shell with TZ set to Pacific/Tahiti to believe that I'm on holiday ;-) > and so behave like other archs with local time RTC. So to resume, what I > need to fix is: > > - change ppc_md.get/set_rtc_time() to set and return the raw time from > the RTC > - at boot, apply only once the offset from nvram, initialize sys_tz and > call do_sys_settimeofday() > - Figure out a way to write back the timezone to nvram (since I think > sys_tz is updated by userland tools via settimeofday, isn't it ?) when > changed. I'm not sure on this last point, the rest looks fine and correct. > >Yes, this is strange, but the original error lies with Apple storing the > >time as local time while keeping also the timezone. I can understand and > >even agree on keeping the timezone and the DST flag in RAM, but then why > >the heck do you want to store the RTC in local time ? It only makes thing > >more complex around DST changes or when changing timezones when you > >travel. I thought Macs were about simplicity... > > Macs are about simplicity, MacOS internals are not ;) ;-) I see... > >Who uses FAT anyway ? I'm going to patch my kernels to kill sys_tz, now > >that I've come to the conclusion that its mere existence is an > >aberration... With an UTC clock, it's the only sensible solution ;-). But > >I don't suggest that everybody should do the same... > > Hum... Done and booted (although I will probably orphan the changeset). Gabriel. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-09 22:13 ` Gabriel Paubert @ 2000-08-09 22:48 ` Benjamin Herrenschmidt 2000-08-10 3:08 ` Gabriel Paubert 2000-08-10 0:00 ` William Blew 1 sibling, 1 reply; 63+ messages in thread From: Benjamin Herrenschmidt @ 2000-08-09 22:48 UTC (permalink / raw) To: Gabriel Paubert, linuxppc-dev >I strongly suspect that we might want a single rtc access function in >ppc_md and add a first parameter telling what we want it to do, the second >being a pointer to a tv_sec, and perhaps more parameters. > >[.../...] > >This last function could also be performed by returning the timebase in >the READ_TIME function as an extra parameter. The best solution is the one >which gives the minimal permanent kernel size, __init code size is >irrelevant. Ok. >What use does it have if no daemon will change the timezone anyway ? Well, when travelling with a PowerBook, you tend to regulary change the timezone, and you like the kernel to remember what it was ;) Paul added the write back of the sys_tz, so I beleive he has some userland tool to set it too, Paul ? With this current code, any write to our pmac-specific /dev/rtc will cause ppc_md.set_rtc_time to update both the RTC and the xpram sys_tz. So either we make a userland tool for that, or eventually add such a feature to pmud along with other PowerBook-specific tasks, accessing / dev/nvram directly, or we find a way to make sure updates to sys_tz are written back to nvram. I was not specifically thinking about results of a DST change. We could eventually add this code along with other nvram write code (for flash based nvram) in the restart/shutdown routines if we don't want to do it from every ppc_md.set >How does MacOS handle DST changes (on the fly or only at reboot) ? On the fly. >You never (well hardldy ever) pass localtime to userland in Unix and >that's a big big big plus, each process/user can set TZ as it wishes. IOW >the value of sys_tz is at best a system wide default but is not imposed to >anybody. Here at the telescope on all Linux machines, /etc/localtime is >set as UTC, but then I set TZ=Europe/Madrid in my .profile to avoid too >much confusion with my PC which has localtime set to Europe/Madrid. And >right now I am running a shell with TZ set to Pacific/Tahiti to believe >that I'm on holiday ;-) Ok, I understand that. That's indeed a nice feature. Changing the "global" timezone is specifically useful for portables. You can consider it as the machine's physical location instead of a kind of "global" timezone. >Done and booted (although I will probably orphan the changeset). Heh ;) Ben. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-09 22:48 ` Benjamin Herrenschmidt @ 2000-08-10 3:08 ` Gabriel Paubert 0 siblings, 0 replies; 63+ messages in thread From: Gabriel Paubert @ 2000-08-10 3:08 UTC (permalink / raw) To: Benjamin Herrenschmidt; +Cc: linuxppc-dev On Thu, 10 Aug 2000, Benjamin Herrenschmidt wrote: > >This last function could also be performed by returning the timebase in > >the READ_TIME function as an extra parameter. The best solution is the one > >which gives the minimal permanent kernel size, __init code size is > >irrelevant. > > Ok. So now it might be time to start coding :-) > >What use does it have if no daemon will change the timezone anyway ? > > Well, when travelling with a PowerBook, you tend to regulary change the > timezone, and you like the kernel to remember what it was ;) Paul added > the write back of the sys_tz, so I beleive he has some userland tool to > set it too, Paul ? Perhaps timeconfig does this. BTW, from hwclock manual on my PC about DST: locality at the present time. In practice, the DST part of the timezone value is almost never used, so if the geo- graphical part were to be set to its correct value, the users of the timezone value would actually compute the wrong local time. Therefore, hwclock violates the definition of the kernel's timezone value and always sets the DST part to zero. If DST is supposed to be in effect, hwclock simply adds an hour to the geographical part. So it's still another convention, where as usual theory and practice are different, but in practice match MacOS RTC. My head hurts... Given the broken FAT code which needs fixing, couldn't we simply decide that DST in the kernel is merely informative and that localtime = UTC - sys_tz.minutes_west (hopefully I got the sign right). > With this current code, any write to our pmac-specific /dev/rtc will > cause ppc_md.set_rtc_time to update both the RTC and the xpram sys_tz. > > So either we make a userland tool for that, or eventually add such a > feature to pmud along with other PowerBook-specific tasks, accessing / > dev/nvram directly, or we find a way to make sure updates to sys_tz are > written back to nvram. I was not specifically thinking about results of a > DST change. We could eventually add this code along with other nvram > write code (for flash based nvram) in the restart/shutdown routines if we > don't want to do it from every ppc_md.set I have no strong feeling about this, maybe I'll have the day I can afford a PowerBook ;-) > > >How does MacOS handle DST changes (on the fly or only at reboot) ? > > On the fly. Ok, that changes a few things in the equation. But I would not like to type `make' around a DST change on a filesystem which uses local time. > Ok, I understand that. That's indeed a nice feature. Changing the > "global" timezone is specifically useful for portables. You can consider > it as the machine's physical location instead of a kind of "global" timezone. I still don't get it. For my portable physical location would be my house, and I might change TZ or /etc/localtime when I travel, but if I have a filesystem which uses localtime, I would prefer these to be correct for the most frequent case: when I'm at home. Otherwise it becomes a nightmare when you have a mixture of local time and UTC filesystems: - I'm in California, I do a copy from ext2 to hfs with local time set to Pacific coast (GMT-8). ext2 timestamp 6 pm, hfs time 10 am I reboot under MacOS (why not), modify the file, let us say that it takes an hour so the modification time is now 11am Reboot under Linux, ls shows ext2 at 10 am, hfs at 11am - now I go back to Europe, I change the kernel timezone to Madrid (GMT+1) ls shows now 7pm for ext2, but 12am for hfs, so the timestamp order has been screwed up. My opinion is that any change which make potentially reorder timestamps between file systems is so bad that it should be avoided at all costs. Conclusion: you should never change the kernel timezone if you don't want this to happen and you have a mixture of UTC and non UTC filesystems. (Note that I did not put a network transfer in the example, if you do this, you rapidly reach the conclusion that you must be able to always get the timestamps back to UTC from whatever the filesystem stores). Hmm, from what I see, HFS+ seems to use UTC filestamps. That's fine. Regards, Gabriel. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-09 22:13 ` Gabriel Paubert 2000-08-09 22:48 ` Benjamin Herrenschmidt @ 2000-08-10 0:00 ` William Blew 1 sibling, 0 replies; 63+ messages in thread From: William Blew @ 2000-08-10 0:00 UTC (permalink / raw) To: Gabriel Paubert; +Cc: Benjamin Herrenschmidt, linuxppc-dev On Thu, 10 Aug 2000, Gabriel Paubert wrote: > On Wed, 9 Aug 2000, Benjamin Herrenschmidt wrote: > How does MacOS handle DST changes (on the fly or only at reboot) ? If I remember correctly this spring my MacOS 9 changed it on the fly. -- William Blew, wblew@home.com Gamer by Choice, Geek by Birth ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-09 8:44 ` Benjamin Herrenschmidt 2000-08-09 11:32 ` Martin Costabel 2000-08-09 13:50 ` Gabriel Paubert @ 2000-08-09 14:26 ` Takashi Oe 2 siblings, 0 replies; 63+ messages in thread From: Takashi Oe @ 2000-08-09 14:26 UTC (permalink / raw) To: Benjamin Herrenschmidt; +Cc: Gabriel Paubert, linuxppc-dev On Wed, 9 Aug 2000, Benjamin Herrenschmidt wrote: > >Until now I've found a single place where sys_tz.dsttime is used in the > >kernel: fs/fat/misc.c when converting between Unix and FAT timestamps. > >Interestingly it's used only in one direction, so it definitely looks like > >a bug. Some other filesystems (affs/hfs/ncpfs/ufs) use the timezone > >information but not the dst field, making FAT time handling look even > >buggier. > > Yep. My understanding (and that's also how MacOS uses it) is that the DST > correction is _included_ in the timezone offset, the dst field beeing > just an indication. So yes, FAT is probably broken. I agree that the way FAT does appear to buggy, but it would be better to use *minuteswest and *dsttime in kernel as in userland IMHO. When localtime() in /usr/include/time.h is called, two global variables are set. One is timezone and the other is daylight, and here is how it works: $ cat t.c #include <stdio.h> #include <time.h> int main() { time_t gmt; struct tm cur_tm; gmt = time( NULL ); cur_tm = *gmtime( &gmt ); printf("UTC %02d:%02d:%02d\n",cur_tm.tm_hour,cur_tm.tm_min,cur_tm.tm_sec); cur_tm = *localtime( &gmt ); printf("local %02d:%02d:%02d\n",cur_tm.tm_hour,cur_tm.tm_min,cur_tm.tm_sec); printf("timezone = %d\n", timezone); printf("daylight = %d\n", daylight); return 0; } $ gcc -o t t.c $ ./t UTC 14:11:31 local 09:11:31 timezone = 21600 daylight = 1 $ As you can see, "timezone" does not include the DST offset, so any applications which care need to use "daylight" flag. Since the kernel's struct timezone has two equivalent fields, I would think it's easier to maintain timezone related codes if its usage are also somewhat equivalent to userland. Otherwise, I see no point in having a separate useless DST info. Takashi Oe ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-08 17:41 ` Benjamin Herrenschmidt 2000-08-08 22:44 ` Gabriel Paubert @ 2000-08-09 0:55 ` Takashi Oe 2000-08-09 8:48 ` Benjamin Herrenschmidt 2000-08-09 14:24 ` Geert Uytterhoeven 2 siblings, 1 reply; 63+ messages in thread From: Takashi Oe @ 2000-08-09 0:55 UTC (permalink / raw) To: Benjamin Herrenschmidt; +Cc: linuxppc-dev On Tue, 8 Aug 2000, Benjamin Herrenschmidt wrote: > - The second one is that ppc_md.get/set_rtc_time are passed (or return) > a time value independently of the timezone. That mean that they either do > no conversion and so it's the responsibility of the caller to "know" if > the RTC is in local time or UTC, or they do the conversion and so return > (and get passed) an UTC time. That's what I decided to do, so on > PowerMac, they do the adjustement from UTC to localtime and the opposite > inside those functions. Paul recently added code to also save the > timezone to the xpram. There's a small semantic problem with this code, > since it takes the time to set to the RTC as a parameter but uses the > global sys_tz. It should either use no parameter (and use only xtime/ > sys_tz), or be passed both parameters. In this case, we can probably move > the init code that reads the initial time zone to the pmac_get_rtc_time() too. Personally, I think UTC <-> local time conversion should be handled in userland. Both hwclock and clock can handle both local time and UTC just fine. Does Mac OS handle different timezone information in xpram well? Timezone information is saved in xpram but it's also saved in some of config files. So, it appears to me that Mac OS will get confused or ignore or delete the timezone setting in xpram if it doesn't agree with the config file. Takashi Oe ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-09 0:55 ` Takashi Oe @ 2000-08-09 8:48 ` Benjamin Herrenschmidt 2000-08-09 16:37 ` Takashi Oe 0 siblings, 1 reply; 63+ messages in thread From: Benjamin Herrenschmidt @ 2000-08-09 8:48 UTC (permalink / raw) To: Takashi Oe, linuxppc-dev >Personally, I think UTC <-> local time conversion should be handled in >userland. Both hwclock and clock can handle both local time and UTC just >fine. If we do that this way, we can't have proper in-kernel NTP update of the RTC without a hack that let it only "correct" for less than 1 hour. >Does Mac OS handle different timezone information in xpram well? Timezone >information is saved in xpram but it's also saved in some of config files. >So, it appears to me that Mac OS will get confused or ignore or delete the >timezone setting in xpram if it doesn't agree with the config file. It used to be only in xpram. Recent MacOS also have a prefs file, I have to check what happens when this file is out of sync with the xpram. Saving the tz to xpram also makes sure the kernel is fine at boot accross multiple boots. It may be a "cultural" difference due to my years of MacOS background, but rather than having userland set the timezone, I'd personally rather see userland read the kernel timezone coming from xpram, and set the appropriate userland env. vars depending on this timezone (especially useful for portables). Well, that's my 2 cents, of course, nobody will agree wit me ;) Ben. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-09 8:48 ` Benjamin Herrenschmidt @ 2000-08-09 16:37 ` Takashi Oe 2000-08-09 22:46 ` Gabriel Paubert 0 siblings, 1 reply; 63+ messages in thread From: Takashi Oe @ 2000-08-09 16:37 UTC (permalink / raw) To: Benjamin Herrenschmidt; +Cc: linuxppc-dev On Wed, 9 Aug 2000, Benjamin Herrenschmidt wrote: > >Personally, I think UTC <-> local time conversion should be handled in > >userland. Both hwclock and clock can handle both local time and UTC just > >fine. > > If we do that this way, we can't have proper in-kernel NTP update of the > RTC without a hack that let it only "correct" for less than 1 hour. Hmm, I don't really understand this NTP update problem. Does NTP even work when the system time is off by more than 1 hour? > >Does Mac OS handle different timezone information in xpram well? Timezone > >information is saved in xpram but it's also saved in some of config files. > >So, it appears to me that Mac OS will get confused or ignore or delete the > >timezone setting in xpram if it doesn't agree with the config file. > > It used to be only in xpram. Recent MacOS also have a prefs file, I have > to check what happens when this file is out of sync with the xpram. Ok, at least on Mac OS 8.6, it looks okay. At each boot, Mac OS honors the timezone setting in xpram over its configuration files, and it always assumes that RTC is in localtime as previously noted. Now, the OS doesn't update its configuration files like for Location Manager, so users will have to deal with it, and that's okay. > Saving the tz to xpram also makes sure the kernel is fine at boot accross > multiple boots. How does kernel know when to update the tz so that it can save the info to xpram? Since do_settimeofday() is not necessarily called when tz is changed, we'd have to save the tz to xpram every time do_settimeofday() is called even when tz is not at all changed. Or is the xpram update only done when *set_rtc() is called? How do you know when to set DST flag on xpram? Isn't it better to have a little userland app do the xpram manipulation? > It may be a "cultural" difference due to my years of MacOS background, > but rather than having userland set the timezone, I'd personally rather > see userland read the kernel timezone coming from xpram, and set the > appropriate userland env. vars depending on this timezone (especially > useful for portables). Well, that's my 2 cents, of course, nobody will > agree wit me ;) /dev/rtc aside, kernel only communicates through UTC, and timezone manipulation is best done in userland especially for portables. When you go from one timezone to another, it requires some sort of userland intervention to get clock right anyway. Let's say /dev/rtc gives raw machine value and since Mac OS requires it to be localtime for P'Mac let me assume /dev/rtc gives localtime which is consistent with xpram timezone info. As long as RTC and xpram timezone info is consistent (it does'nt have to be the correct timezone where the machine happens to be at the time), kernel can always figure out what UTC is at very early boot time. If /dev/rtc time and kernel UTC derived localtime (via /etc/localtime) do not agree, we know something has happened and we can decide or ask users to set xpram timezone info (via /dev/nvram or whatever) or change /etc/localtime link or whatever at boot time or user specified time. And, if /dev/rtc time and kernel UTC derived localtime do agree, all is well and we have nothing to do. Either way, there is nothing for kernel to decide. See? Takashi Oe ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-09 16:37 ` Takashi Oe @ 2000-08-09 22:46 ` Gabriel Paubert 0 siblings, 0 replies; 63+ messages in thread From: Gabriel Paubert @ 2000-08-09 22:46 UTC (permalink / raw) To: Takashi Oe; +Cc: Benjamin Herrenschmidt, linuxppc-dev On Wed, 9 Aug 2000, Takashi Oe wrote: > > On Wed, 9 Aug 2000, Benjamin Herrenschmidt wrote: > > > >Personally, I think UTC <-> local time conversion should be handled in > > >userland. Both hwclock and clock can handle both local time and UTC just > > >fine. > > > > If we do that this way, we can't have proper in-kernel NTP update of the > > RTC without a hack that let it only "correct" for less than 1 hour. > > Hmm, I don't really understand this NTP update problem. Does NTP even > work when the system time is off by more than 1 hour? Oh yes, it will simply call settimeofday if the error is large or adjtimex if it's small enough to drift smoothly in a reasonable time. The question is, will it update the RTC correctly ? It depends on many things, my PC clock was off by 20 minutes and it did not update the RTC (limit is about 15 minutes since there are half hours time zones). I had to use hwclock --systohc --utc to set it up once I had ntp running and locked on a server, now te kernel automatically takes care of it. > > It used to be only in xpram. Recent MacOS also have a prefs file, I have > > to check what happens when this file is out of sync with the xpram. > > Ok, at least on Mac OS 8.6, it looks okay. At each boot, Mac OS honors > the timezone setting in xpram over its configuration files, and it always > assumes that RTC is in localtime as previously noted. Now, the OS doesn't > update its configuration files like for Location Manager, so users will > have to deal with it, and that's okay. Confused, but I've hardly ever even seen a Mac. > How does kernel know when to update the tz so that it can save the info to > xpram? Since do_settimeofday() is not necessarily called when tz is > changed, we'd have to save the tz to xpram every time do_settimeofday() is > called even when tz is not at all changed. Or is the xpram update only > done when *set_rtc() is called? How do you know when to set DST flag on > xpram? > > Isn't it better to have a little userland app do the xpram manipulation? Is it actually even necessary to manipulate it. Once the kernel clock is in UTC, everything is userland under Unix. If MacOS detects that DST has changed after a reboot, let it handle this, as long as it allows to find UTC from RTC and xpram everything is fine. > > > It may be a "cultural" difference due to my years of MacOS background, > > but rather than having userland set the timezone, I'd personally rather > > see userland read the kernel timezone coming from xpram, and set the > > appropriate userland env. vars depending on this timezone (especially > > useful for portables). Well, that's my 2 cents, of course, nobody will > > agree wit me ;) > > /dev/rtc aside, kernel only communicates through UTC, and timezone > manipulation is best done in userland especially for portables. When you > go from one timezone to another, it requires some sort of userland > intervention to get clock right anyway. Indeed... > Let's say /dev/rtc gives raw machine value and since Mac OS requires it to > be localtime for P'Mac let me assume /dev/rtc gives localtime which is > consistent with xpram timezone info. As long as RTC and xpram timezone > info is consistent (it does'nt have to be the correct timezone where the > machine happens to be at the time), kernel can always figure out what UTC > is at very early boot time. If /dev/rtc time and kernel UTC derived > localtime (via /etc/localtime) do not agree, we know something has > happened and we can decide or ask users to set xpram timezone info (via Why ? On a portable it may simply mean that you are away and set /etc/localtime to your new zone or anything else, but I'd rather keep the filesystem timestamps on my FAT/hfs partitions to the local timestamps of my default location. As long as I don't boot MacOS while I'm away there is perhaps no reason to change the xpram offset... > /dev/nvram or whatever) or change /etc/localtime link or whatever at boot > time or user specified time. And, if /dev/rtc time and kernel UTC derived > localtime do agree, all is well and we have nothing to do. Either way, > there is nothing for kernel to decide. See? No policy in the kernel in indeed a good guideline. Gabriel. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-08 17:41 ` Benjamin Herrenschmidt 2000-08-08 22:44 ` Gabriel Paubert 2000-08-09 0:55 ` Takashi Oe @ 2000-08-09 14:24 ` Geert Uytterhoeven 2 siblings, 0 replies; 63+ messages in thread From: Geert Uytterhoeven @ 2000-08-09 14:24 UTC (permalink / raw) To: Benjamin Herrenschmidt; +Cc: Michael Schmitz, linuxppc-dev On Tue, 8 Aug 2000, Benjamin Herrenschmidt wrote: > - The first one, well hidden in kernel/time.c (generic code) is the call > to warp_time(). This is an awful hack that seem to be done because PCs > apparently also set the RTC to local time. This hack will cause the It depends: Linux-only PCs are encouraged to run the RTC in UTC, while you have to run the RTC in local time if you want Linux to coexist with some other OSses, e.g. those from Redmond. Which one is used is specified in user space. On Debian (I'm using 2.1 on an isa32 box right here), I have the lines # Set GMT="-u" if your system clock is set to GMT, and GMT="" if not. GMT="-u" in /etc/default/rcS. Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
[parent not found: <20000804205524.383@192.168.1.10>]
* Re: rtc again... [not found] <20000804205524.383@192.168.1.10> @ 2000-08-05 1:10 ` Takashi Oe 2000-08-05 11:25 ` Benjamin Herrenschmidt 0 siblings, 1 reply; 63+ messages in thread From: Takashi Oe @ 2000-08-05 1:10 UTC (permalink / raw) To: Benjamin Herrenschmidt; +Cc: linuxppc-dev On Fri, 4 Aug 2000, Benjamin Herrenschmidt wrote: > >Ok, the usage of "sys_tz" or "struct timezone" in general in kernel is not > >well defined or confused. kernel/time.c seems to assume "tz_minuteswest" > >includes DST fix up, while fs/fat/misc.c uses "tz_minuteswest" for time > >zone and "tz_dsttime" for DST fix up. The code in pmac_set_rtc_time() > >doesn't work if "tz_minuteswest" doesn't include the DST fix up, so, if > >that's the correct behaviour, the following code in pmac_time_init() needs > >to be tweaked for consistency in my opinion from: > > > > sys_tz.tz_minuteswest = -delta/60; > > /* I _suppose_ this is 0:off, 1:on */ > > sys_tz.tz_dsttime = dst; > > > >to > > > > sys_tz.tz_minuteswest = -delta/60 - (dst? 60: 0); > > sys_tz.tz_dsttime = dst; > > Well, who is right ? time.c or fs/fat/misc.c ? Maybe we should query the > powers that be... Did you look at what the userland hwclock expects in > tz_dsttime ? As Geert has pointed out, hwclock can give UTC or local time to /dev/rtc, why don't we just let userland deal with this local time issue. What I mean is for pmac_set_rtc_time(), let's change: nowtime += RTC_OFFSET - sys_tz.tz_minuteswest * 60; to nowtime += RTC_OFFSET; and we assume that userland will give us the correct local time. For pmac_time_init(), let's change: sys_tz.tz_minuteswest = -delta/60; /* I _suppose_ this is 0:off, 1:on */ sys_tz.tz_dsttime = dst; to sys_tz.tz_minuteswest = -delta/60 - (dst? 60: 0); sys_tz.tz_dsttime = 0; which is what's been done in hwclock source and a reasonable compromise, I think, so that both kernel/time.c and fs/fat/misc.c would be happy. How about it? Takashi Oe ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-05 1:10 ` Takashi Oe @ 2000-08-05 11:25 ` Benjamin Herrenschmidt 2000-08-05 14:44 ` Takashi Oe 0 siblings, 1 reply; 63+ messages in thread From: Benjamin Herrenschmidt @ 2000-08-05 11:25 UTC (permalink / raw) To: Takashi Oe, linuxppc-dev > >As Geert has pointed out, hwclock can give UTC or local time to /dev/rtc, >why don't we just let userland deal with this local time issue. What I >mean is for pmac_set_rtc_time(), let's change: That would give us back what we had at the beginning. This way, userland is solely responsible for this setup, which means it will be wrong on 50% of user machines (but that's user fault isn't it ?) and which means the kernel will boot with a wrong time, at least until the userland init script takes over. I don't see why it's such a mess to simply read the default values from xpram so we are consistent with MacOS. But everything in Linux is a mess anyway... Ben. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-05 11:25 ` Benjamin Herrenschmidt @ 2000-08-05 14:44 ` Takashi Oe 0 siblings, 0 replies; 63+ messages in thread From: Takashi Oe @ 2000-08-05 14:44 UTC (permalink / raw) To: Benjamin Herrenschmidt; +Cc: linuxppc-dev On Sat, 5 Aug 2000, Benjamin Herrenschmidt wrote: > > > >As Geert has pointed out, hwclock can give UTC or local time to /dev/rtc, > >why don't we just let userland deal with this local time issue. What I > >mean is for pmac_set_rtc_time(), let's change: > > That would give us back what we had at the beginning. This way, userland > is solely responsible for this setup, which means it will be wrong on 50% > of user machines (but that's user fault isn't it ?) and which means the > kernel will boot with a wrong time, at least until the userland init > script takes over. Hmm, nothing has been changed with pmac_get_rtc_time(). So, if it is broken now, it was broken before.... Seriously, pmac_get_rtc_time() is the one responsible for giving you the correct time at boot time, isn't it? Does xtime need to be in UTC? If so, is it feasible to let ppc_md.time_init() give an offset in seconds from UTC to the time given by RTC? void __init time_init(void) { unsigned long flags; + int offset = 0; if (ppc_md.time_init != NULL) { offset = ppc_md.time_init(); } ... write_lock_irqsave(&xtime_lock, flags); - xtime.tv_sec = ppc_md.get_rtc_time(); + xtime.tv_sec = ppc_md.get_rtc_time() + offset; write_unlock_irqrestore(&xtime_lock, flags); ... Oh, and change time_sleep_notify() in pmac_time.c accordingly. > I don't see why it's such a mess to simply read the default values from > xpram so we are consistent with MacOS. But everything in Linux is a mess > anyway... Maybe because pmac's RTC is in local time for one? Takashi Oe ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again...
@ 2000-08-03 11:24 Iain Sandoe
0 siblings, 0 replies; 63+ messages in thread
From: Iain Sandoe @ 2000-08-03 11:24 UTC (permalink / raw)
To: Franz Sirl; +Cc: linuxppc-dev
On Thu, Aug 3, 2000, Franz Sirl wrote:
> At 11:00 03.08.00, Martin Costabel wrote:
>>Iain Sandoe wrote:
>> >
>> > Hi,
>> >
>> > under 2.2.17pre15ben1
>> >
>> > rtc does not give me the right answer when built in - what am I doing
>> wrong?
>> >
>> > It won't build load as a module right now 'cos I forgot to check ppc_ksyms
>> > before doing the build :-( .... (I remembered for 2.4.0).
>> >
>> > under 2.4.0-test5 it seems to be fine as a module (haven't tried built in).
>>
>>I am using it as module both for 2.2.17-bk and for 2.4.0-test5. They
>>don't give the same time, and I think it is the one in 2.4.0 that is
>>right. I am at GMT+2:00, and the time in 2.2.17 is 2 hours early. When I
>>change /etc/sysconfig/clock from "UTC=false" to "UTC=true", both times
>>shift by 2 hours, but the discrepancy remains.
>
> Are you sure you are using the "hwclock" utility coming with util-linux?
> And not the old pmac specific "clock" utility to query the clock? What
> happens if you remove all "clock" binaries from your system?
yeah, I checked this. (although the sbin/clock binary was still there
originally - I removed it).
No change - it's going to take a harder look - later today with luck.
Iain.
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 63+ messages in thread* Re: rtc again... @ 2000-08-03 9:56 Iain Sandoe 2000-08-03 10:13 ` Benjamin Herrenschmidt 2000-08-03 11:58 ` Martin Costabel 0 siblings, 2 replies; 63+ messages in thread From: Iain Sandoe @ 2000-08-03 9:56 UTC (permalink / raw) To: Benjamin Herrenschmidt, martin costabel, linuxppc-dev and the 2.2.17pre15 dmesg contains the lines: ==== Linux version 2.2.17pre15-ben1-snd (root@athena) (gcc version 2.95.2 19991024 (release/franzo)) #2 Wed Aug 2 23:16:52 BST 2000 [...] pmac nvram is core99: 0 System has 64 possible interrupts GMT Delta read from XPRAM: 60 minutes, DST: on ==== which, as I said, works as long as RTC is -not- involved. are we applying a correct twice? Iain. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-03 9:56 Iain Sandoe @ 2000-08-03 10:13 ` Benjamin Herrenschmidt 2000-08-03 11:58 ` Martin Costabel 1 sibling, 0 replies; 63+ messages in thread From: Benjamin Herrenschmidt @ 2000-08-03 10:13 UTC (permalink / raw) To: Iain Sandoe, linuxppc-dev > >which, as I said, works as long as RTC is -not- involved. >are we applying a correct twice? I beleive it may be a userland crap doing wrong things with /dev/rtc ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-03 9:56 Iain Sandoe 2000-08-03 10:13 ` Benjamin Herrenschmidt @ 2000-08-03 11:58 ` Martin Costabel 1 sibling, 0 replies; 63+ messages in thread From: Martin Costabel @ 2000-08-03 11:58 UTC (permalink / raw) To: Iain Sandoe; +Cc: Benjamin Herrenschmidt, linuxppc-dev Iain Sandoe wrote: > > and the 2.2.17pre15 dmesg contains the lines: > > ==== > Linux version 2.2.17pre15-ben1-snd (root@athena) (gcc version 2.95.2 > 19991024 (release/franzo)) #2 Wed Aug 2 23:16:52 BST 2000 > [...] > pmac nvram is core99: 0 > System has 64 possible interrupts > GMT Delta read from XPRAM: 60 minutes, DST: on > > ==== > > which, as I said, works as long as RTC is -not- involved. > are we applying a correct twice? This is my impression, too. My clock is set to localtime (according to MacOS, clock -r, and hwclock -r --localtime). Pre-rtc 2.2.x and 2.4.0-test5 give the same system time as MacOS, but 2.2.17pre13 with Ben's patch is 2 hours early, that is, it sets system time to UTC. It is not surprising that 2.2.17-pre13-bk and 2.4.0-test5 don't give the same result, because the former contains Ben's offset patch and the latter doesn't. The question is only which one is right. Another observation from /var/log/messages (since Ben was talking about the early system time before rc.sysinit does its job): In the 2.4.0-test5 boot messages, I see a few that have the wrong time (localtime+2 hours). These are the actions done by rc.sysinit before the clock gets set (mounting /proc and setting kernel parameters). On the other hand, all kernel messages show the correct time. In the boot messages from 2.2.17, with or without Ben's patch, there are no messages with a wrong time (except when all of them have the wrong time :-)). But then I admit don't understand what the timestamps in log/messages mean. They certainly don't indicate the time when the actions happened. The kernel messages have later timestamps than the rc.sysinit actions. And in 2.4.x the order of these messages is completely different from the one in 2.2.x. -- Martin ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again...
@ 2000-08-03 9:41 Iain Sandoe
0 siblings, 0 replies; 63+ messages in thread
From: Iain Sandoe @ 2000-08-03 9:41 UTC (permalink / raw)
To: Benjamin Herrenschmidt, martin costabel, linuxppc-dev
>>I am using it as module both for 2.2.17-bk and for 2.4.0-test5. They
>>don't give the same time, and I think it is the one in 2.4.0 that is
>>right. I am at GMT+2:00, and the time in 2.2.17 is 2 hours early. When I
>>change /etc/sysconfig/clock from "UTC=false" to "UTC=true", both times
>>shift by 2 hours, but the discrepancy remains.
>>
>>The following patch for bitkeeper linuxppc_2_2 fixes this problem for
>>me. It brings 2.2.17pre13 in line with 2.4.0-test5 (and MacOS). I cannot
>>test the VIAPMU part, so maybe there the offset is necessary, but for
>>the VIACUDA part, it seems wrong.
>
> You patch reverts a fix I made some time ago. Basially, what probably
> happens is that your RTC is in UTC time, not in local time. The Mac RTC
> is supposed to be in local time, the offset corrects the kernel time on
> boot to account for this. Previously, without that fix, the kernel used
> to boot with a bogus UTC time until userland fixes it.
Hm. I have exactly the same phenomenon.
I reset my RTC using NTP (on the Mac Side) last night and have daylight
saving set to "automatic". The Mac timezone is correct (GB). The Linux
timezone is also correct (GB). I can't see any other random offsets around
the system.
If rtc is left out (and the module won't/isn't loaded). 2.2.17pre15 gets
the time right (UTC+0100).
If rtc is complied in (and I imagine the same will apply to a working
module) 2.217pre15 gets it one hour wrong. (UTC)
Under 2.4.0-t5 it's OK (well, it agrees with MacOS)...
Note that it has *always* been right with earlier versions of 2.2.x.
Unless, of course, Apple have changed to storing UTC in the transition to
9.0.4 (might ease the way to X?)
Iain.
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 63+ messages in thread* rtc again... @ 2000-08-02 22:48 Iain Sandoe 2000-08-03 9:00 ` Martin Costabel 0 siblings, 1 reply; 63+ messages in thread From: Iain Sandoe @ 2000-08-02 22:48 UTC (permalink / raw) To: linuxppc-dev Hi, under 2.2.17pre15ben1 rtc does not give me the right answer when built in - what am I doing wrong? It won't build load as a module right now 'cos I forgot to check ppc_ksyms before doing the build :-( .... (I remembered for 2.4.0). under 2.4.0-test5 it seems to be fine as a module (haven't tried built in). Iain. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-02 22:48 Iain Sandoe @ 2000-08-03 9:00 ` Martin Costabel 2000-08-03 9:30 ` Benjamin Herrenschmidt 2000-08-03 10:31 ` Franz Sirl 0 siblings, 2 replies; 63+ messages in thread From: Martin Costabel @ 2000-08-03 9:00 UTC (permalink / raw) To: linuxppc-dev; +Cc: Iain Sandoe [-- Attachment #1: Type: text/plain, Size: 941 bytes --] Iain Sandoe wrote: > > Hi, > > under 2.2.17pre15ben1 > > rtc does not give me the right answer when built in - what am I doing wrong? > > It won't build load as a module right now 'cos I forgot to check ppc_ksyms > before doing the build :-( .... (I remembered for 2.4.0). > > under 2.4.0-test5 it seems to be fine as a module (haven't tried built in). I am using it as module both for 2.2.17-bk and for 2.4.0-test5. They don't give the same time, and I think it is the one in 2.4.0 that is right. I am at GMT+2:00, and the time in 2.2.17 is 2 hours early. When I change /etc/sysconfig/clock from "UTC=false" to "UTC=true", both times shift by 2 hours, but the discrepancy remains. The following patch for bitkeeper linuxppc_2_2 fixes this problem for me. It brings 2.2.17pre13 in line with 2.4.0-test5 (and MacOS). I cannot test the VIAPMU part, so maybe there the offset is necessary, but for the VIACUDA part, it seems wrong. -- Martin [-- Attachment #2: pmac_time.patch --] [-- Type: text/plain, Size: 1027 bytes --] --- arch/ppc/kernel/pmac_time.c~ Mon Jun 26 09:09:05 2000 +++ arch/ppc/kernel/pmac_time.c Thu Aug 3 09:22:36 2000 @@ -78,7 +78,6 @@ unsigned long pmac_get_rtc_time(void) { struct adb_request req; - int offset = sys_tz.tz_minuteswest * 60; /* Get the time from the RTC */ if (adb_controller == 0) @@ -95,7 +94,7 @@ printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n", req.reply_len); return (req.reply[3] << 24) + (req.reply[4] << 16) - + (req.reply[5] << 8) + req.reply[6] - RTC_OFFSET + offset; + + (req.reply[5] << 8) + req.reply[6] - RTC_OFFSET; case ADB_VIAPMU: if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) { printk("pmac_read_rtc_time: pmu_request failed\n"); @@ -107,7 +106,7 @@ printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n", req.reply_len); return (req.reply[1] << 24) + (req.reply[2] << 16) - + (req.reply[3] << 8) + req.reply[4] - RTC_OFFSET + offset; + + (req.reply[3] << 8) + req.reply[4] - RTC_OFFSET; default: return 0; } ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-03 9:00 ` Martin Costabel @ 2000-08-03 9:30 ` Benjamin Herrenschmidt 2000-08-03 10:54 ` Gabriel Paubert 2000-08-03 10:31 ` Franz Sirl 1 sibling, 1 reply; 63+ messages in thread From: Benjamin Herrenschmidt @ 2000-08-03 9:30 UTC (permalink / raw) To: Martin Costabel, linuxppc-dev, Iain Sandoe >I am using it as module both for 2.2.17-bk and for 2.4.0-test5. They >don't give the same time, and I think it is the one in 2.4.0 that is >right. I am at GMT+2:00, and the time in 2.2.17 is 2 hours early. When I >change /etc/sysconfig/clock from "UTC=false" to "UTC=true", both times >shift by 2 hours, but the discrepancy remains. > >The following patch for bitkeeper linuxppc_2_2 fixes this problem for >me. It brings 2.2.17pre13 in line with 2.4.0-test5 (and MacOS). I cannot >test the VIAPMU part, so maybe there the offset is necessary, but for >the VIACUDA part, it seems wrong. You patch reverts a fix I made some time ago. Basially, what probably happens is that your RTC is in UTC time, not in local time. The Mac RTC is supposed to be in local time, the offset corrects the kernel time on boot to account for this. Previously, without that fix, the kernel used to boot with a bogus UTC time until userland fixes it. Ben. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-03 9:30 ` Benjamin Herrenschmidt @ 2000-08-03 10:54 ` Gabriel Paubert 2000-08-03 11:14 ` Benjamin Herrenschmidt ` (3 more replies) 0 siblings, 4 replies; 63+ messages in thread From: Gabriel Paubert @ 2000-08-03 10:54 UTC (permalink / raw) To: Benjamin Herrenschmidt; +Cc: Martin Costabel, linuxppc-dev, Iain Sandoe On Thu, 3 Aug 2000, Benjamin Herrenschmidt wrote: > > >I am using it as module both for 2.2.17-bk and for 2.4.0-test5. They > >don't give the same time, and I think it is the one in 2.4.0 that is > >right. I am at GMT+2:00, and the time in 2.2.17 is 2 hours early. When I > >change /etc/sysconfig/clock from "UTC=false" to "UTC=true", both times > >shift by 2 hours, but the discrepancy remains. > > > >The following patch for bitkeeper linuxppc_2_2 fixes this problem for > >me. It brings 2.2.17pre13 in line with 2.4.0-test5 (and MacOS). I cannot > >test the VIAPMU part, so maybe there the offset is necessary, but for > >the VIACUDA part, it seems wrong. > > You patch reverts a fix I made some time ago. Basially, what probably > happens is that your RTC is in UTC time, not in local time. The Mac RTC > is supposed to be in local time, the offset corrects the kernel time on > boot to account for this. Previously, without that fix, the kernel used > to boot with a bogus UTC time until userland fixes it. Actually given the problems with RTC being UTC or local time, the offset might perhaps better be setup as a kernel parameter so that th system start up in a known good state. It seems that it is in RAM for Macs, but what about other machines (I have no problems since all my machines are UTC and I simply refuse to use an OS which requires anything else) ? Ok, I have since long promised a patch for 2.4 to improve the clock precision, here it is (relative to kernel.org 2.4.0-test5) but it has only been tested on my MVME boards. There is still quite a long TODO list I have added to time.c but at least stability is there on UP machines at least (it should work perfectly on SMP if timebases are in sync). I have doubts about 8xx: it won't work if the timebase is really running below 1 MHz, but you can't expect 1 microsecond resolution timestamps either in this case. The fix is quite easy however but requires an additional global variable. And no, I did not change the names of global variables for fun but to get linker error until the kernel would build. Note that I have removed the #if 0 to prevent RTC update from Bemjamin, the code was completely bogus to start with: you should only update the RTC when STA_UNSYNC is clear, not when it is set. If you are using NTP, you don't need anything else: set CONFIG_PPC_RTC off, NTP does RTC updates through adjtimex and this should simply work right out of the box with this patch, at least it does for me and the clock is very stable. I still see tremendously large long term drifts (of the order of 1 ppm) but this is due to the fact that el cheapo crystals on computers are actually narrowband noise sources and not precision oscillators. Please test and give feedbcak. Gabriel. ===== arch/ppc/kernel/apus_setup.c 1.2 vs 1.3 ===== --- 1.2/arch/ppc/kernel/apus_setup.c Tue Apr 25 19:58:46 2000 +++ 1.3/arch/ppc/kernel/apus_setup.c Thu Jul 13 14:06:48 2000 @@ -304,7 +304,7 @@ void apus_calibrate_decr(void) { #ifdef CONFIG_APUS - int freq, divisor; + unsigned long freq; /* This algorithm for determining the bus speed was contributed by Ralph Schmidt. */ @@ -335,8 +335,8 @@ bus_speed = 60; freq = 15000000; } else if ((bus_speed >= 63) && (bus_speed < 69)) { - bus_speed = 66; - freq = 16500000; + bus_speed = 67; + freq = 16666667; } else { printk ("APUS: Unable to determine bus speed (%d). " "Defaulting to 50MHz", bus_speed); @@ -375,12 +375,10 @@ } - freq *= 60; /* try to make freq/1e6 an integer */ - divisor = 60; - printk("time_init: decrementer frequency = %d/%d\n", freq, divisor); - decrementer_count = freq / HZ / divisor; - count_period_num = divisor; - count_period_den = freq / 1000000; + printk("time_init: decrementer frequency = %lu.%.6lu MHz\n", + freq/1000000, freq%1000000); + tb_ticks_per_jiffy = freq / HZ; + tb_to_us = mulhwu_scale_factor(freq, 1000000); __bus_speed = bus_speed; __speed_test_failed = speed_test_failed; ===== arch/ppc/kernel/chrp_time.c 1.3 vs 1.5 ===== --- 1.3/arch/ppc/kernel/chrp_time.c Mon May 15 16:53:30 2000 +++ 1.5/arch/ppc/kernel/chrp_time.c Sat Jul 29 19:54:16 2000 @@ -26,7 +26,7 @@ #include <asm/nvram.h> #include <asm/prom.h> #include <asm/init.h> -#include "time.h" +#include <asm/time.h> static int nvram_as1 = NVRAM_AS1; static int nvram_as0 = NVRAM_AS0; @@ -155,8 +155,7 @@ void __init chrp_calibrate_decr(void) { struct device_node *cpu; - int *fp, divisor; - unsigned long freq; + unsigned long freq, *fp; if (via_calibrate_decr()) return; @@ -168,15 +167,13 @@ freq = 16666000; /* hardcoded default */ cpu = find_type_devices("cpu"); if (cpu != 0) { - fp = (int *) get_property(cpu, "timebase-frequency", NULL); + fp = (unsigned long *) + get_property(cpu, "timebase-frequency", NULL); if (fp != 0) - freq = *fp; + freq = *fp; } - freq *= 30; - divisor = 30; - printk("time_init: decrementer frequency = %lu/%d (%ld MHz)\n", freq, - divisor, (freq/divisor)>>20); - decrementer_count = freq / HZ / divisor; - count_period_num = divisor; - count_period_den = freq / 1000000; + printk("time_init: decrementer frequency = %lu.%.6lu MHz\n", + freq/1000000, freq%1000000); + tb_ticks_per_jiffy = freq / HZ; + tb_to_us = mulhwu_scale_factor(freq, 1000000); } ===== arch/ppc/kernel/pmac_time.c 1.2 vs 1.5 ===== --- 1.2/arch/ppc/kernel/pmac_time.c Mon Jun 19 19:59:36 2000 +++ 1.5/arch/ppc/kernel/pmac_time.c Mon Jul 31 11:28:27 2000 @@ -26,7 +26,8 @@ #include <asm/pgtable.h> #include <asm/machdep.h> -#include "time.h" +#include <asm/time.h> +#include <asm/nvram.h> extern rwlock_t xtime_lock; @@ -54,8 +55,30 @@ /* Bits in IFR and IER */ #define T1_INT 0x40 /* Timer 1 interrupt */ -__pmac +extern struct timezone sys_tz; + +__init +void pmac_time_init(void) +{ +#ifdef CONFIG_NVRAM + s32 delta = 0; + int dst; + + delta = ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x9)) << 16; + delta |= ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xa)) << 8; + delta |= pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xb); + if (delta & 0x00800000UL) + delta |= 0xFF000000UL; + dst = ((pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x8) & 0x80) != 0); + printk("GMT Delta read from XPRAM: %d minutes, DST: %s\n", delta/60, + dst ? "on" : "off"); + sys_tz.tz_minuteswest = -delta/60; + /* I _suppose_ this is 0:off, 1:on */ + sys_tz.tz_dsttime = dst; +#endif +} +__pmac unsigned long pmac_get_rtc_time(void) { #ifdef CONFIG_ADB @@ -95,7 +118,39 @@ int pmac_set_rtc_time(unsigned long nowtime) { - return 0; +#ifdef CONFIG_ADB + struct adb_request req; +#endif + nowtime += RTC_OFFSET - sys_tz.tz_minuteswest * 60; + + switch (sys_ctrler) { +#ifdef CONFIG_ADB_CUDA + case SYS_CTRLER_CUDA: + if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME, + nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0) + return 0; + while (!req.complete) + cuda_poll(); +// if (req.reply_len != 7) + printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n", + req.reply_len); + return 1; +#endif /* CONFIG_ADB_CUDA */ +#ifdef CONFIG_ADB_PMU + case SYS_CTRLER_PMU: + if (pmu_request(&req, NULL, 5, PMU_SET_RTC, + nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0) + return 0; + while (!req.complete) + pmu_poll(); + if (req.reply_len != 5) + printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n", + req.reply_len); + return 1; +#endif /* CONFIG_ADB_PMU */ + default: + return 0; + } } /* @@ -136,12 +191,11 @@ ; dend = get_dec(); - decrementer_count = (dstart - dend) / 6; - count_period_num = 60; - count_period_den = decrementer_count * 6 * HZ / 100000; + tb_ticks_per_jiffy = (dstart - dend) / 6; + tb_to_us = mulhwu_scale_factor(dstart - dend, 60000); - printk(KERN_INFO "via_calibrate_decr: decrementer_count = %u (%u ticks)\n", - decrementer_count, dstart - dend); + printk(KERN_INFO "via_calibrate_decr: tb_ticks_per_jiffy = %u (%u ticks)\n", + tb_ticks_per_jiffy, dstart - dend); return 1; } @@ -164,8 +218,10 @@ case PBOOK_WAKE: write_lock_irqsave(&xtime_lock, flags); xtime.tv_sec = pmac_get_rtc_time() + time_diff; + set_dec(tb_ticks_per_jiffy); + /* No PBOOK has a 601 AFAIK, so use get_tbl not binary_tbl */ + tb_last_stamp=get_tbl(); xtime.tv_usec = 0; - set_dec(decrementer_count); last_rtc_update = xtime.tv_sec; write_unlock_irqrestore(&xtime_lock, flags); break; @@ -186,7 +242,7 @@ void __init pmac_calibrate_decr(void) { struct device_node *cpu; - int freq, *fp, divisor; + unsigned long freq, *fp; #ifdef CONFIG_PMAC_PBOOK pmu_register_sleep_notifier(&time_sleep_notifier); @@ -202,15 +258,13 @@ cpu = find_type_devices("cpu"); if (cpu == 0) panic("can't find cpu node in time_init"); - fp = (int *) get_property(cpu, "timebase-frequency", NULL); + fp = (unsigned long *) get_property(cpu, "timebase-frequency", NULL); if (fp == 0) panic("can't get cpu timebase frequency"); - freq = *fp * 60; /* try to make freq/1e6 an integer */ - divisor = 60; - printk("time_init: decrementer frequency = %d/%d\n", - freq, divisor); - decrementer_count = freq / HZ / divisor; - count_period_num = divisor; - count_period_den = freq / 1000000; + freq = *fp; + printk("time_init: decrementer frequency = %lu.%.6lu MHz\n", + freq/1000000, freq%1000000); + tb_ticks_per_jiffy = freq / HZ; + tb_to_us = mulhwu_scale_factor(freq, 1000000); } ===== arch/ppc/kernel/ppc_ksyms.c 1.8 vs 1.10 ===== --- 1.8/arch/ppc/kernel/ppc_ksyms.c Wed Jul 12 15:20:37 2000 +++ 1.10/arch/ppc/kernel/ppc_ksyms.c Sat Jul 29 19:54:20 2000 @@ -281,7 +281,7 @@ EXPORT_SYMBOL(irq_desc); void ppc_irq_dispatch_handler(struct pt_regs *, int); EXPORT_SYMBOL(ppc_irq_dispatch_handler); -EXPORT_SYMBOL(decrementer_count); +EXPORT_SYMBOL(tb_ticks_per_jiffy); EXPORT_SYMBOL(get_wchan); EXPORT_SYMBOL(console_drivers); EXPORT_SYMBOL(console_lock); ===== arch/ppc/kernel/prep_setup.c 1.3 vs 1.5 ===== --- 1.3/arch/ppc/kernel/prep_setup.c Tue Jun 6 16:52:46 2000 +++ 1.5/arch/ppc/kernel/prep_setup.c Sat Jul 29 19:54:20 2000 @@ -49,7 +49,7 @@ #include <asm/raven.h> #include <asm/keyboard.h> -#include "time.h" +#include <asm/time.h> #include "local_irq.h" #include "i8259.h" #include "open_pic.h" @@ -377,14 +377,13 @@ */ void __init prep_res_calibrate_decr(void) { - int freq, divisor; + unsigned long freq, divisor=4; freq = res->VitalProductData.ProcessorBusHz; - divisor = 4; - printk("time_init: decrementer frequency = %d/%d\n", freq, divisor); - decrementer_count = freq / HZ / divisor; - count_period_num = divisor; - count_period_den = freq / 1000000; + printk("time_init: decrementer frequency = %lu.%.6lu MHz\n", + (freq/divisor)/1000000, (freq/divisor)%1000000); + tb_ticks_per_jiffy = freq / HZ / divisor; + tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000); } /* @@ -393,32 +392,30 @@ * but on prep we have to figure it out. * -- Cort */ -int calibrate_done = 0; -volatile int *done_ptr = &calibrate_done; +/* Done with 3 interrupts: the first one primes the cache and the + * 2 following ones measure the interval. The precision of the method + * is still doubtful due to the short interval sampled. + */ +static __initdata volatile int calibrate_steps = 3; +static __initdata unsigned tbstamp; void __init prep_calibrate_decr_handler(int irq, void *dev, struct pt_regs *regs) { - unsigned long freq, divisor; - static unsigned long t1 = 0, t2 = 0; - - if ( !t1 ) - t1 = get_dec(); - else if (!t2) - { - t2 = get_dec(); - t2 = t1-t2; /* decr's in 1/HZ */ - t2 = t2*HZ; /* # decrs in 1s - thus in Hz */ - freq = t2 * 60; /* try to make freq/1e6 an integer */ - divisor = 60; - printk("time_init: decrementer frequency = %lu/%lu (%luMHz)\n", - freq, divisor,t2>>20); - decrementer_count = freq / HZ / divisor; - count_period_num = divisor; - count_period_den = freq / 1000000; - *done_ptr = 1; + unsigned long t, freq; + int step=--calibrate_steps; + + t = get_tbl(); + if (step > 0) { + tbstamp = t; + } else { + freq = (t - tbstamp)*HZ; + printk("time_init: decrementer frequency = %lu.%.6lu MHz\n", + freq/1000000, freq%1000000); + tb_ticks_per_jiffy = freq / HZ; + tb_to_us = mulhwu_scale_factor(freq, 1000000); } } @@ -440,7 +437,7 @@ if (request_irq(0, prep_calibrate_decr_handler, 0, "timer", NULL) != 0) panic("Could not allocate timer IRQ!"); __sti(); - while ( ! *done_ptr ) /* nothing */; /* wait for calibrate */ + while ( calibrate_steps ) /* nothing */; /* wait for calibrate */ restore_flags(flags); free_irq( 0, NULL); } @@ -449,8 +446,8 @@ /* We use the NVRAM RTC to time a second to calibrate the decrementer. */ void __init mk48t59_calibrate_decr(void) { - unsigned long freq, divisor; - unsigned long t1, t2; + unsigned long freq; + unsigned long t1; unsigned char save_control; long i; unsigned char sec; @@ -470,29 +467,31 @@ /* Read the seconds value to see when it changes. */ sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS); + /* Actually this is bad for precicion, we should have a loop in + * which we only read the seconds counter. nvram_read_val writes + * the address bytes on every call and this takes a lot of time. + * Perhaps an nvram_wait_change method returning a time + * stamp with a loop count as parameter would be the solution. + */ for (i = 0 ; i < 1000000 ; i++) { /* may take up to 1 second... */ + t1 = get_tbl(); if (ppc_md.nvram_read_val(MK48T59_RTC_SECONDS) != sec) { break; } } - t1 = get_dec(); sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS); for (i = 0 ; i < 1000000 ; i++) { /* Should take up 1 second... */ + freq = get_tbl()-t1; if (ppc_md.nvram_read_val(MK48T59_RTC_SECONDS) != sec) { break; } } - t2 = t1 - get_dec(); - - freq = t2 * 60; /* try to make freq/1e6 an integer */ - divisor = 60; - printk("time_init: decrementer frequency = %lu/%lu (%luMHz)\n", - freq, divisor,t2>>20); - decrementer_count = freq / HZ / divisor; - count_period_num = divisor; - count_period_den = freq / 1000000; + printk("time_init: decrementer frequency = %lu.%.6lu MHz\n", + freq/1000000, freq%1000000); + tb_ticks_per_jiffy = freq / HZ; + tb_to_us = mulhwu_scale_factor(freq, 1000000); } void __prep ===== arch/ppc/kernel/time.c 1.4 vs 1.7 ===== --- 1.4/arch/ppc/kernel/time.c Mon Jun 19 19:59:36 2000 +++ 1.7/arch/ppc/kernel/time.c Wed Aug 2 13:24:39 2000 @@ -5,7 +5,28 @@ * Written by Cort Dougan (cort@cs.nmt.edu) to merge * Paul Mackerras' version and mine for PReP and Pmac. * MPC8xx/MBX changes by Dan Malek (dmalek@jlc.net). + * + * First round of bugfixes by Gabriel Paubert (paubert@iram.es) + * to make clock more stable (2.4.0-test5). The only thing + * that this code assumes is that the timebases have been synchronized + * by firmware on SMP and are never stopped (never do sleep + * on SMP then, nap and doze are OK). + * + * TODO (not necessarily in this file): + * - improve precicion and reproducibility of timebase frequency + * measurement at boot time. + * - get rid of xtime_lock for gettimeofday (generic kernel problem + * to be implemented on all architectures for SMP scalability and + * eventually implementing gettimeofday without entering the kernel). + * - put all time/clock related variables in a single structure + * to minimize number of cache lines touched by gettimeofday() + * - for astronomical applications: add a new function to get + * non ambiguous timestamps even around leap seconds. This needs + * a new timestamp format and a good name. + * * + * The following comment is partially obsolete (at least the long wait + * is no more a valid reason): * Since the MPC8xx has a programmable interrupt timer, I decided to * use that rather than the decrementer. Two reasons: 1.) the clock * frequency is low, causing 2.) a long wait in the timer interrupt @@ -44,24 +65,22 @@ #include <asm/8xx_immap.h> #include <asm/machdep.h> -#include "time.h" +#include <asm/time.h> void smp_local_timer_interrupt(struct pt_regs *); /* keep track of when we need to update the rtc */ -time_t last_rtc_update = 0; +time_t last_rtc_update; extern rwlock_t xtime_lock; /* The decrementer counts down by 128 every 128ns on a 601. */ #define DECREMENTER_COUNT_601 (1000000000 / HZ) -#define COUNT_PERIOD_NUM_601 1 -#define COUNT_PERIOD_DEN_601 1000 -unsigned decrementer_count; /* count value for 1e6/HZ microseconds */ -unsigned count_period_num; /* 1 decrementer count equals */ -unsigned count_period_den; /* count_period_num / count_period_den us */ -unsigned long last_tb; +unsigned tb_ticks_per_jiffy; +unsigned tb_to_us; +unsigned tb_last_stamp; +extern unsigned long wall_jiffies; /* * timer_interrupt - gets called when the decrementer overflows, * with interrupts disabled. @@ -69,8 +88,8 @@ */ int timer_interrupt(struct pt_regs * regs) { - int dval, d; - unsigned long flags; + int delta; + unsigned local_stamp = tb_last_stamp; unsigned long cpu = smp_processor_id(); hardirq_enter(cpu); @@ -95,47 +114,47 @@ } #endif /* CONFIG_SMP */ - dval = get_dec(); - /* - * Wait for the decrementer to change, then jump - * in and add decrementer_count to its value - * (quickly, before it changes again!) - */ - while ((d = get_dec()) == dval) - ; - asm volatile("mftb %0" : "=r" (last_tb) ); - /* - * Don't play catchup between the call to time_init() - * and sti() in init/main.c. - * - * This also means if we're delayed for > HZ - * we lose those ticks. If we're delayed for > HZ - * then we have something wrong anyway, though. - * - * -- Cort + /* This might fail on 601 SMP systems, are there any out there ? + * The right way to do it might be to add a per CPU timebase stamp + * in the per CPU interrupt structure. Would this be acceptable ? */ - if ( d < (-1*decrementer_count) ) - d = 0; - set_dec(d + decrementer_count); - if ( !smp_processor_id() ) - { + while ((delta = tb_ticks_per_jiffy-tb_ticks_since(local_stamp)) <=0) { + + local_stamp += tb_ticks_per_jiffy; + if (smp_processor_id()) continue; + /* We are in an interrupt, no need to save/restore flags */ + write_lock(&xtime_lock); + tb_last_stamp = local_stamp; do_timer(regs); /* - * update the rtc when needed + * update the rtc when needed, this should be performed on the + * right fraction of a second. Half or full second ? + * Full second works on mk48t59 clocks, others need testing. + * Note that this update is basically only used through + * the adjtimex system calls. Setting the HW clock in + * any other way is a /dev/rtc and userland business. + * This is still wrong by -0.5/+1.5 jiffies because of the + * timer interrupt resolution and possible delay, but here we + * hit a quantization limit which can only be solved by higher + * resolution timers and decoupling time management from timer + * interrupts. + * We should have an rtc call that only sets the minutes and + * seconds like on Intel to avoid problems with non UTC clocks. */ - read_lock_irqsave(&xtime_lock, flags); - if ( (time_status & STA_UNSYNC) && - ((xtime.tv_sec > last_rtc_update + 60) || - (xtime.tv_sec < last_rtc_update)) ) - { - if (ppc_md.set_rtc_time(xtime.tv_sec) == 0) - last_rtc_update = xtime.tv_sec; + if ( (time_status & STA_UNSYNC) == 0 && + xtime.tv_sec - last_rtc_update >= 659 && + xtime.tv_usec >= 1000000 - 1500000/HZ && + xtime.tv_usec <= 1000000 - 500000/HZ && + jiffies-wall_jiffies == 1) { + if (ppc_md.set_rtc_time(xtime.tv_sec+1) == 0) + last_rtc_update = xtime.tv_sec+1; else - /* do it again in 60 s */ - last_rtc_update = xtime.tv_sec; + /* Try again one minute later */ + last_rtc_update += 60; } - read_unlock_irqrestore(&xtime_lock, flags); + write_unlock(&xtime_lock); } + set_dec(delta); #ifdef CONFIG_SMP smp_local_timer_interrupt(regs); #endif @@ -152,46 +171,57 @@ */ void do_gettimeofday(struct timeval *tv) { - unsigned long flags, diff; + unsigned long flags; + unsigned delta, lost_ticks, usec, sec; - save_flags(flags); - cli(); read_lock_irqsave(&xtime_lock, flags); - *tv = xtime; + sec = xtime.tv_sec; + usec = xtime.tv_usec; + delta = tb_ticks_since(tb_last_stamp); + lost_ticks = jiffies-wall_jiffies; read_unlock_irqrestore(&xtime_lock, flags); - /* XXX we don't seem to have the decrementers synced properly yet */ -#ifndef CONFIG_SMP - asm volatile("mftb %0" : "=r" (diff) ); - diff -= last_tb; - tv->tv_usec += diff * count_period_num / count_period_den; - tv->tv_sec += tv->tv_usec / 1000000; - tv->tv_usec = tv->tv_usec % 1000000; -#endif - restore_flags(flags); + usec += mulhwu(tb_to_us, tb_ticks_per_jiffy*lost_ticks + delta); + while (usec>1000000) { + sec++; + usec -= 1000000; + } + tv->tv_sec = sec; + tv->tv_usec = usec; } void do_settimeofday(struct timeval *tv) { unsigned long flags; - int frac_tick; - - last_rtc_update = 0; /* so the rtc gets updated soon */ + int tv_delta; - frac_tick = tv->tv_usec % (1000000 / HZ); - save_flags(flags); - cli(); write_lock_irqsave(&xtime_lock, flags); - xtime.tv_sec = tv->tv_sec; - xtime.tv_usec = tv->tv_usec - frac_tick; - write_unlock_irqrestore(&xtime_lock, flags); - set_dec(frac_tick * count_period_den / count_period_num); + /* the rtc has to be updated soon but *not* *now* to avoid + * introducing random fractional second offsets. Do not attempt the + * update before the next second boundary. Actually, it will not + * be updated until STA_UNSYNC is cleared. Note also that + * we don't touch the decrementer since: + * a) it would lose timer interrupt synchronization on SMP + * b) it could make one jiffy spuriously shorter or longer + * which would introduce another source of uncertainty potentially + * harmful to relatively short timers. + * In short, jiffies are always updated at regular intervals + * and it's the clock wall time (xtime) which is adjusted and + * is not always a multiple of 1/Hz seconds. + */ + + tv_delta = mulhwu(tb_to_us, tb_ticks_since(tb_last_stamp)); + xtime.tv_sec = tv->tv_sec - ((tv_delta>tv->tv_usec) ? 1 : 0); + xtime.tv_usec = tv->tv_usec + ((tv_delta>tv->tv_usec) ? + 1000000 : 0) - tv_delta; + last_rtc_update = xtime.tv_sec - 658; + time_adjust = 0; /* stop active adjtime() */ time_status |= STA_UNSYNC; time_state = TIME_ERROR; /* p. 24, (a) */ time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; - restore_flags(flags); + write_unlock_irqrestore(&xtime_lock, flags); } @@ -203,23 +233,23 @@ ppc_md.time_init(); } - if ((_get_PVR() >> 16) == 1) { + if (__USE_RTC()) { /* 601 processor: dec counts down by 128 every 128ns */ - decrementer_count = DECREMENTER_COUNT_601; - count_period_num = COUNT_PERIOD_NUM_601; - count_period_den = COUNT_PERIOD_DEN_601; + tb_ticks_per_jiffy = DECREMENTER_COUNT_601; + /* mulhwu_scale_factor(1000000000, 1000000) is 0x418937 */ + tb_to_us = 0x418937; } else if (!smp_processor_id()) { ppc_md.calibrate_decr(); } write_lock_irqsave(&xtime_lock, flags); xtime.tv_sec = ppc_md.get_rtc_time(); + tb_last_stamp = get_native_tbl(); + set_dec(tb_ticks_per_jiffy); xtime.tv_usec = 0; + /* No update now, we just read the time from the RTC ! */ + last_rtc_update = xtime.tv_sec; write_unlock_irqrestore(&xtime_lock, flags); - - set_dec(decrementer_count); - /* allow setting the time right away */ - last_rtc_update = 0; } /* Converts Gregorian date to seconds since 1970-01-01 00:00:00. @@ -344,3 +374,37 @@ */ GregorianDay(tm); } + +/* Auxiliary function to compute scaling factors */ +/* Actually the choice of a timebase running at 1/4 the of the bus + * frequency giving resolution of a few tens of nanoseconds is quite nice. + * It makes this computation very precise (27-28 bits typically) which + * is optimistic considering the stability of most processor clock + * oscillators and the precision with which the timebase frequency + * is measured but does not harm. + */ +unsigned mulhwu_scale_factor(unsigned inscale, unsigned outscale) { + unsigned mlt=0, tmp, err; + /* No concern for performance, it's done once: use a stupid + * but safe and compact method to find the multiplier. + */ + for (tmp = 1U<<31; tmp != 0; tmp >>= 1) { + if (mulhwu(inscale, mlt|tmp) < outscale) mlt|=tmp; + } + /* We might still be off by 1 for the best approximation. + * A side effect of this is that if outscale is too large + * the returned value will be zero. + * Many corner cases have been checked and seem to work, + * some might have been forgotten in the test however. + * The precision for typical values (outscale is 1 million), + * inscale is between a few millions to a few tens of + * millions is 27-28 bits, which is optimistic about the + * quality of 99.99% CPU clock oscillators (and the precision + * with which the frequency is measured at boot with the current + * setup) but does no harm. + */ + err = inscale*(mlt+1); + if (err <= inscale/2) mlt++; + return mlt; +} + ===== include/asm-ppc/time.h 1.1 vs 1.4 ===== --- 1.1/arch/ppc/kernel/time.h Mon Jun 5 16:03:49 2000 +++ 1.4/include/asm-ppc/time.h Wed Aug 2 13:24:39 2000 @@ -12,9 +12,10 @@ #include <asm/processor.h> /* time.c */ -extern unsigned decrementer_count; -extern unsigned count_period_num; -extern unsigned count_period_den; +extern unsigned tb_ticks_per_jiffy; +extern unsigned tb_to_us; +extern unsigned tb_last_stamp; + extern unsigned long mktime(unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); extern void to_tm(int tim, struct rtc_time * tm); @@ -40,3 +41,73 @@ mtspr(SPRN_DEC, val); #endif } + +/* Accessor functions for the timebase (RTC on 601) registers. */ +/* If one day CONFIG_POWER is added just define __USE_RTC as 1 */ +#ifdef CONFIG_6xx +extern __inline__ int const __USE_RTC(void) { + return (mfspr(SPRN_PVR)>>16) == 1; +} +#else +#define __USE_RTC() 0 +#endif + +extern __inline__ unsigned long get_tbl(void) { + unsigned long tbl; + asm volatile("mftb %0" : "=r" (tbl)); + return tbl; +} + +extern __inline__ unsigned long get_rtcl(void) { + unsigned long rtcl; + asm volatile("mfrtcl %0" : "=r" (rtcl)); + return rtcl; +} + +extern __inline__ unsigned get_native_tbl(void) { + if (__USE_RTC()) + return get_rtcl(); + else + return get_tbl(); +} + +/* On machines with RTC, this function can only be used safely + * after the timestamp and for 1 second. It is only used by gettimeofday + * however so it should not matter. + */ +extern __inline__ unsigned tb_ticks_since(unsigned tstamp) { + if (__USE_RTC()) { + int delta = get_rtcl() - tstamp; + return delta<0 ? delta + 1000000000 : delta; + } else { + return get_tbl() - tstamp; + } +} + +#if 0 +extern __inline__ unsigned long get_bin_rtcl(void) { + unsigned long rtcl, rtcu1, rtcu2; + asm volatile("\ +1: mfrtcu %0\n\ + mfrtcl %1\n\ + mfrtcu %2\n\ + cmpw %0,%2\n\ + bne- 1b\n" + : "=r" (rtcu1), "=r" (rtcl), "=r" (rtcu2) + : : "cr0"); + return rtcu2*1000000000+rtcl; +} + +extern __inline__ unsigned binary_tbl(void) { + if (__USE_RTC()) + return get_bin_rtcl(); + else + return get_tbl(); +} +#endif + +/* Use mulhwu to scale processor timebase to timeval */ +#define mulhwu(x,y) \ +({unsigned z; asm ("mulhwu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;}) + +unsigned mulhwu_scale_factor(unsigned, unsigned); ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-03 10:54 ` Gabriel Paubert @ 2000-08-03 11:14 ` Benjamin Herrenschmidt 2000-08-03 11:25 ` Gabriel Paubert 2000-08-03 11:45 ` Gabriel Paubert 2000-08-03 23:33 ` Takashi Oe ` (2 subsequent siblings) 3 siblings, 2 replies; 63+ messages in thread From: Benjamin Herrenschmidt @ 2000-08-03 11:14 UTC (permalink / raw) To: Gabriel Paubert, linuxppc-dev > >Actually given the problems with RTC being UTC or local time, the offset >might perhaps better be setup as a kernel parameter so that th system >start up in a known good state. It seems that it is in RAM for Macs, but >what about other machines (I have no problems since all my machines are >UTC and I simply refuse to use an OS which requires anything else) ? Most "sane" RTCs are in UTC. On PReP and CHRP, this is not a problem, they use, I think, legacy RTC hardware and so you just need to set it up correctly in UTC. On Macs, it's slightly different. MacOS expects the RTC to be in local time and stores the timezone and DSL state in PRAM. I recently added fixup code in pmac_time.c for reading that value and correctly setting the kernel timezone at boot from it. Paul improved on my code by adding the ability to save modified timezone back to PRAM. I think there's still an issue with DST. There's a field for storing it in the kernel tz structure, but I'm not sure it's fully defined or used. I beleive this could be easily fixed by looking at what hwclock does, and eventually fixing it. Note that all this affects only powermacs, and the /dev/rtc driver we are talking about here is the pmac-only one in drivers/macintosh. >Note that I have removed the #if 0 to prevent RTC update from Bemjamin, >the code was completely bogus to start with: you should only update the >RTC when STA_UNSYNC is clear, not when it is set. If you are using NTP, >you don't need anything else: set CONFIG_PPC_RTC off, NTP does RTC updates >through adjtimex and this should simply work right out of the box with >this patch, at least it does for me and the clock is very stable. Did you remove the #if 0 or did you remove the code that is #if 0'ed ? That code seem to originate from other archs and was causing a lot of trouble when enabling the pmac_rtc_set_time() since it was writing bogus times to the RTC during boot (at that time, I didn't yet added the code to read the timezone from the PRAM). Also, I didn't see why the kernel would keep updating the RTC hardware, the sounded bogus to me and a userland matter, not a kernel matter (but maybe I missed something). So I #if'ed it out. Removing it completely sounds fine. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-03 11:14 ` Benjamin Herrenschmidt @ 2000-08-03 11:25 ` Gabriel Paubert 2000-08-03 11:45 ` Gabriel Paubert 1 sibling, 0 replies; 63+ messages in thread From: Gabriel Paubert @ 2000-08-03 11:25 UTC (permalink / raw) To: Benjamin Herrenschmidt; +Cc: linuxppc-dev On Thu, 3 Aug 2000, Benjamin Herrenschmidt wrote: > > > >Actually given the problems with RTC being UTC or local time, the offset > >might perhaps better be setup as a kernel parameter so that th system > >start up in a known good state. It seems that it is in RAM for Macs, but > >what about other machines (I have no problems since all my machines are > >UTC and I simply refuse to use an OS which requires anything else) ? > > Most "sane" RTCs are in UTC. On PReP and CHRP, this is not a problem, > they use, I think, legacy RTC hardware and so you just need to set it up > correctly in UTC. > > On Macs, it's slightly different. MacOS expects the RTC to be in local > time and stores the timezone and DSL state in PRAM. I recently added > fixup code in pmac_time.c for reading that value and correctly setting > the kernel timezone at boot from it. Paul improved on my code by adding > the ability to save modified timezone back to PRAM. I think there's still > an issue with DST. There's a field for storing it in the kernel tz > structure, but I'm not sure it's fully defined or used. I beleive this > could be easily fixed by looking at what hwclock does, and eventually > fixing it. > > Note that all this affects only powermacs, and the /dev/rtc driver we are > talking about here is the pmac-only one in drivers/macintosh. > > >Note that I have removed the #if 0 to prevent RTC update from Bemjamin, > >the code was completely bogus to start with: you should only update the > >RTC when STA_UNSYNC is clear, not when it is set. If you are using NTP, > >you don't need anything else: set CONFIG_PPC_RTC off, NTP does RTC updates > >through adjtimex and this should simply work right out of the box with > >this patch, at least it does for me and the clock is very stable. > > Did you remove the #if 0 or did you remove the code that is #if 0'ed ? > That code seem to originate from other archs and was causing a lot of > trouble when enabling the pmac_rtc_set_time() since it was writing bogus > times to the RTC during boot (at that time, I didn't yet added the code > to read the timezone from the PRAM). > Also, I didn't see why the kernel would keep updating the RTC hardware, > the sounded bogus to me and a userland matter, not a kernel matter (but > maybe I missed something). So I #if'ed it out. Removing it completely > sounds fine. No, I removed the #if 0, it was the condition STA_UNSYNC which was not correctly tested (inverted actually), and was missing a few additional conditions (on fractional seconds and so on): - at boot you set STA_UNSYNC to prevent RTC updates (the inverted test made that RTC was updated asap instead), - if you use NTP (as I do) the system uses adjtimex syscall to write into the RTC at regular intervals. NTP does not use /dev/rtc, it phases locks to another good source and lets the kernel update the RTC at regular intervals. This is how it works on all other archs, why would you want to add a full featured RTC driver when you only need a small subset (and this guarantees that your system time will be more or less correct when it reboots and ntp has trouble connecting to the time server) ? Anyway, we might need something like the Intel port which only sets the minutes and seconds of the RTC for automatic RC updates. The problem is that the Intel code is wrong too (it can get the hours wrong if you change only the minutes). For the rest I looked at the Intel and Alpha code before doing my patch, and I'm fairly sure that is is for the most part correct given the results here (I'm rebooting regularly a machine and noting the offsets of ntpdate at each reboot to be sure that I have got the fractional second right). As I said I want this patch tested, it might break some machines but will be a major timekeeping improvement for all other. Gabriel. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-03 11:14 ` Benjamin Herrenschmidt 2000-08-03 11:25 ` Gabriel Paubert @ 2000-08-03 11:45 ` Gabriel Paubert 2000-08-03 13:25 ` Benjamin Herrenschmidt 1 sibling, 1 reply; 63+ messages in thread From: Gabriel Paubert @ 2000-08-03 11:45 UTC (permalink / raw) To: Benjamin Herrenschmidt; +Cc: linuxppc-dev On Thu, 3 Aug 2000, Benjamin Herrenschmidt wrote: > Most "sane" RTCs are in UTC. On PReP and CHRP, this is not a problem, > they use, I think, legacy RTC hardware and so you just need to set it up > correctly in UTC. Once upon a time, there was also NT for PowerPC, anyway using anything else than UTC in this world is simply madness (it gives ambiguous dates close to DST transition and is a mess in a connected world). I'm now fighting problems with possible ambiguous timestamps around leap seconds (only 1 every 18 months or so but they may be a killer in my case), and trying to build a clean interface to get non ambiguous timestamps at 23:59:60 when it happens. (See what the kernel does in this case in kernel/timer.c about leap second processing, it simply sets the clock back one second and sets the TIME_OOP flag but there are additional problems if you want to get a non ambiguous timestamp in an interrupt between the timer interrupt and the following bottom-half). RTC in CHRP and PreP are varied and far between. I'm still waiting for the new Motorola MVME boards in which they have increased the NVRAM size and the RTC is at the end, another set of quirks in perspective. > On Macs, it's slightly different. MacOS expects the RTC to be in local > time and stores the timezone and DSL state in PRAM. I recently added > fixup code in pmac_time.c for reading that value and correctly setting > the kernel timezone at boot from it. Paul improved on my code by adding > the ability to save modified timezone back to PRAM. I think there's still > an issue with DST. There's a field for storing it in the kernel tz > structure, but I'm not sure it's fully defined or used. I beleive this > could be easily fixed by looking at what hwclock does, and eventually > fixing it. Do you have to change the clock every spring and autumn in MacOS ? Or is it automatic ? Gabriel. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-03 11:45 ` Gabriel Paubert @ 2000-08-03 13:25 ` Benjamin Herrenschmidt 0 siblings, 0 replies; 63+ messages in thread From: Benjamin Herrenschmidt @ 2000-08-03 13:25 UTC (permalink / raw) To: Gabriel Paubert, linuxppc-dev > >Do you have to change the clock every spring and autumn in MacOS ? Or is >it automatic ? MacOS has software to do this automatically. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-03 10:54 ` Gabriel Paubert 2000-08-03 11:14 ` Benjamin Herrenschmidt @ 2000-08-03 23:33 ` Takashi Oe 2000-08-04 8:55 ` Gabriel Paubert [not found] ` <Pine.LNX.3.96LJ1.1b7.1000803182949.650C-100000@ofey.earthl ink.net> 2000-08-04 13:20 ` Geert Uytterhoeven 3 siblings, 1 reply; 63+ messages in thread From: Takashi Oe @ 2000-08-03 23:33 UTC (permalink / raw) To: Gabriel Paubert Cc: Benjamin Herrenschmidt, Martin Costabel, linuxppc-dev, Iain Sandoe On Thu, 3 Aug 2000, Gabriel Paubert wrote: > ===== arch/ppc/kernel/pmac_time.c 1.2 vs 1.5 ===== > --- 1.2/arch/ppc/kernel/pmac_time.c Mon Jun 19 19:59:36 2000 > +++ 1.5/arch/ppc/kernel/pmac_time.c Mon Jul 31 11:28:27 2000 [...] > int pmac_set_rtc_time(unsigned long nowtime) > { > - return 0; > +#ifdef CONFIG_ADB > + struct adb_request req; > +#endif > + nowtime += RTC_OFFSET - sys_tz.tz_minuteswest * 60; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This needs to be changed to + nowtime += RTC_OFFSET - sys_tz.tz_minuteswest * 60 + (sys_tz.tz_dsttime? 3600: 0); Takashi Oe ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-03 23:33 ` Takashi Oe @ 2000-08-04 8:55 ` Gabriel Paubert 2000-08-04 15:25 ` David Edelsohn 0 siblings, 1 reply; 63+ messages in thread From: Gabriel Paubert @ 2000-08-04 8:55 UTC (permalink / raw) To: Takashi Oe Cc: Benjamin Herrenschmidt, Martin Costabel, linuxppc-dev, Iain Sandoe On Thu, 3 Aug 2000, Takashi Oe wrote: > On Thu, 3 Aug 2000, Gabriel Paubert wrote: > > > ===== arch/ppc/kernel/pmac_time.c 1.2 vs 1.5 ===== > > --- 1.2/arch/ppc/kernel/pmac_time.c Mon Jun 19 19:59:36 2000 > > +++ 1.5/arch/ppc/kernel/pmac_time.c Mon Jul 31 11:28:27 2000 > [...] > > int pmac_set_rtc_time(unsigned long nowtime) > > { > > - return 0; > > +#ifdef CONFIG_ADB > > + struct adb_request req; > > +#endif > > + nowtime += RTC_OFFSET - sys_tz.tz_minuteswest * 60; > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > This needs to be changed to > > + nowtime += RTC_OFFSET - sys_tz.tz_minuteswest * 60 + (sys_tz.tz_dsttime? 3600: 0); That's not my code, I took it from linux-2.4.0-test5, and I just added the CONFIG_ADB tests so that it links with a PreP config. I want people to check my patch, with or without NTP and to stress the machines. All clock drifts should have vanished, which was the single most important goal of this patch. Anyway I have very strong opinions about running non UTC clocks and I won't repeat myslef here. The other important points are: - gettimeofday is faster (no divide, a single mulhwu which can't overflow by definition), - 601 support (also faster than in my previous patch but could be wrong on SMP 601. There is a solution however). What I need to know from people with an SMP machine: - are the timebases synchronized ? Or is there a way to synchronize them ? There are solutions for non synchronized timebases, but they are more complex so I wrote the simple solution first. Regards, Gabriel. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-04 8:55 ` Gabriel Paubert @ 2000-08-04 15:25 ` David Edelsohn 2000-08-04 15:50 ` Benjamin Herrenschmidt 2000-08-07 11:51 ` Gabriel Paubert 0 siblings, 2 replies; 63+ messages in thread From: David Edelsohn @ 2000-08-04 15:25 UTC (permalink / raw) To: Gabriel Paubert Cc: Takashi Oe, Benjamin Herrenschmidt, Martin Costabel, linuxppc-dev, Iain Sandoe >>>>> Gabriel Paubert writes: Gabriel> What I need to know from people with an SMP machine: Gabriel> - are the timebases synchronized ? Or is there a way to synchronize them ? On RS/6000 CHRP (RS/6000 Platform Architecture), RTAS provides freeze-time-base and thaw-time-base calls which signal all of the processors inan SMP complex to stop and start the TB. I do not know of any functionality within the PowerPC architecture which would allow processors to coordinate their TBs without some external intervention. Normally AIX boot freezes the TB, zeroes the TB on each processor, and then starts the timebase synchronized. Because the functionality is part of RTAS, this can be done at any time. I do not know what PreP SMP systems do and I know that Apple discourages use of RTAS because it is not intended to work. David ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-04 15:25 ` David Edelsohn @ 2000-08-04 15:50 ` Benjamin Herrenschmidt 2000-08-07 12:33 ` Gabriel Paubert 2000-08-07 11:51 ` Gabriel Paubert 1 sibling, 1 reply; 63+ messages in thread From: Benjamin Herrenschmidt @ 2000-08-04 15:50 UTC (permalink / raw) To: David Edelsohn, linuxppc-dev > > On RS/6000 CHRP (RS/6000 Platform Architecture), RTAS provides >freeze-time-base and thaw-time-base calls which signal all of the >processors inan SMP complex to stop and start the TB. I do not know of >any functionality within the PowerPC architecture which would allow >processors to coordinate their TBs without some external intervention. > > Normally AIX boot freezes the TB, zeroes the TB on each processor, >and then starts the timebase synchronized. Because the functionality is >part of RTAS, this can be done at any time. I do not know what PreP SMP >systems do and I know that Apple discourages use of RTAS because it is not >intended to work. On recent Core99 machines, Apple has a HW timer in the KeyLargo ASIC that can be used to sync timebases. (It looks like a 64 bits bus-cycle timer, but I'm not completely sure yet). There's also, I beleive, the OpenPIC timer. Ben. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-04 15:50 ` Benjamin Herrenschmidt @ 2000-08-07 12:33 ` Gabriel Paubert 0 siblings, 0 replies; 63+ messages in thread From: Gabriel Paubert @ 2000-08-07 12:33 UTC (permalink / raw) To: Benjamin Herrenschmidt; +Cc: David Edelsohn, linuxppc-dev On Fri, 4 Aug 2000, Benjamin Herrenschmidt wrote: > On recent Core99 machines, Apple has a HW timer in the KeyLargo ASIC that > can be used to sync timebases. (It looks like a 64 bits bus-cycle timer, > but I'm not completely sure yet). There's also, I beleive, the OpenPIC timer. OpenPIC timers are not that easy to use since they are not guaranteed to ultimately run off the same oscillator as the processor time base, so you can't guarantee a stable mathematical relationship between the timebase and an OpenPIC timer count register. Of course it will work in many machines (you would have to sacrifice one of the 4 timers to do this but that's not a big deal). You would also have to keep the most significant timebase bits and some other data in some other places (the OpenPIC timer has only 31 bits and runs at 1/8 the bus clock on integrated Motorola OpenPICs but 1/8 the PCI clock if you have an IBM MPIC2 chip). I'm looking for a solution for SMP which does not depend on the exact underlying hardware (it may require IPI but these are quite well encapsulated), like a few interlocked memory accesses to transmit the timebase and check that they are close enough. Oh, BTW, in the OpenPIC timer specification the following is so laughable: - integral number of clock ticks per second Knowing that this number is required to be >= 4 million and the stability of typical computer oscillators, I can guarantee that the fractional part can be used as a fairly good random number generator (provided you don't measure it too often). Regards, Gabriel. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-04 15:25 ` David Edelsohn 2000-08-04 15:50 ` Benjamin Herrenschmidt @ 2000-08-07 11:51 ` Gabriel Paubert 2000-08-07 13:18 ` Benjamin Herrenschmidt ` (2 more replies) 1 sibling, 3 replies; 63+ messages in thread From: Gabriel Paubert @ 2000-08-07 11:51 UTC (permalink / raw) To: David Edelsohn Cc: Takashi Oe, Benjamin Herrenschmidt, Martin Costabel, linuxppc-dev, Iain Sandoe On Fri, 4 Aug 2000, David Edelsohn wrote: > On RS/6000 CHRP (RS/6000 Platform Architecture), RTAS provides > freeze-time-base and thaw-time-base calls which signal all of the > processors inan SMP complex to stop and start the TB. I do not know of > any functionality within the PowerPC architecture which would allow > processors to coordinate their TBs without some external intervention. > > Normally AIX boot freezes the TB, zeroes the TB on each processor, > and then starts the timebase synchronized. Because the functionality is > part of RTAS, this can be done at any time. I do not know what PreP SMP > systems do and I know that Apple discourages use of RTAS because it is not > intended to work. Thanks for the info. AFAIK most (all?) PPC processors have a TBEN pin to enable the timebase (whether it affects the decrementer or not is irrelevant). On some chipsets (Motorola Falcon or Hawk at least) a few bits in a system control register are designated to control these pins with one bit per processor (although I fail to see why you would want to enable or disable the timebases individually). Hard reset also clears the timebase on all the processors I know, so the time bases should be synchronized unless the firmware plays with them (assuming the HRESET pins are wired together). However, all I needed to know is whether the firmware will start the machine with the timebases synchronized or not. As long as they are, the patch I suggested should work and give consistent, microsecond resolution gettimeofday on SMP. Actually only the low 32 bits of the timebase are used in the current code (even on 64 bit processors BTW) but I'd expect all 64 bits to be in sync anyway. The only problem is to know what happens on SMP when a processor enters a deep low power mode which stops the timebase. Synchronizing again the timebase is not easy, probably system dependant and I don't have any system to test it. For now I'll treat it as a `don't do it, then' since ultimate power saving measures are not necessary in existing SMP systems. Can anybody with a Macintosh SMP G4 confirm that the time bases are synchronized at boot ? Gabriel (still waiting for test results on the patch, including 601 machines). ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-07 11:51 ` Gabriel Paubert @ 2000-08-07 13:18 ` Benjamin Herrenschmidt 2000-08-07 15:14 ` David Edelsohn 2000-08-08 1:39 ` Paul Mackerras 2 siblings, 0 replies; 63+ messages in thread From: Benjamin Herrenschmidt @ 2000-08-07 13:18 UTC (permalink / raw) To: Gabriel Paubert, linuxppc-dev >Can anybody with a Macintosh SMP G4 confirm that the time bases are >synchronized at boot ? AFAIK, on those machines, I think Apple uses their "timer" device in the new version of the mac-io ASIC to sync. timebases. Reading Apple's CPU startup code in Darwin is _very_ interesting in fact. That's for example how I learned that the only way to correctly and completely flush the cache is to either reserve CPU-specific regions of memory, use the ROM, or have external HW assist. Without that, any snooping on the bus will garbage the flush process. Ben. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-07 11:51 ` Gabriel Paubert 2000-08-07 13:18 ` Benjamin Herrenschmidt @ 2000-08-07 15:14 ` David Edelsohn 2000-08-07 21:16 ` Gabriel Paubert 2000-08-08 1:39 ` Paul Mackerras 2 siblings, 1 reply; 63+ messages in thread From: David Edelsohn @ 2000-08-07 15:14 UTC (permalink / raw) To: Gabriel Paubert Cc: Takashi Oe, Benjamin Herrenschmidt, Martin Costabel, linuxppc-dev, Iain Sandoe Not all processors of an SMP complex are started at power-up and the call to start secodary processors may perform a reset, so I don't think that one can guarantee that the TB's are synchronized. Maybe it all just works, but it does not seem like a requirement of any SMP system design. David ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-07 15:14 ` David Edelsohn @ 2000-08-07 21:16 ` Gabriel Paubert 0 siblings, 0 replies; 63+ messages in thread From: Gabriel Paubert @ 2000-08-07 21:16 UTC (permalink / raw) To: David Edelsohn Cc: Takashi Oe, Benjamin Herrenschmidt, Martin Costabel, linuxppc-dev, Iain Sandoe On Mon, 7 Aug 2000, David Edelsohn wrote: > Not all processors of an SMP complex are started at power-up and > the call to start secodary processors may perform a reset, so I don't > think that one can guarantee that the TB's are synchronized. Maybe it all > just works, but it does not seem like a requirement of any SMP system > design. Yes, you may perform a reset. But at least on the chipsets I have seen the reset pin you have access to is the soft reset input which does not clear the TB (nor set the MSR IP bit for example). If the HRESET inputs are wired together (from a power supply monitoring circuit or something similar) and the timebase is never written to, than they should be synchronized. Then the only remaining problems are the power saving modes that may stop the timebase... Disclaimer: this is how it works on 6xx/7xx processors as they are implemented in most systems. I don't know anything about IBM specific CPUs like Power3/Power4... Gabriel. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-07 11:51 ` Gabriel Paubert 2000-08-07 13:18 ` Benjamin Herrenschmidt 2000-08-07 15:14 ` David Edelsohn @ 2000-08-08 1:39 ` Paul Mackerras 2000-08-11 11:04 ` Gabriel Paubert 2 siblings, 1 reply; 63+ messages in thread From: Paul Mackerras @ 2000-08-08 1:39 UTC (permalink / raw) To: Gabriel Paubert; +Cc: linuxppc-dev Gabriel Paubert writes: > Hard reset also clears the timebase on all the processors I know, so the > time bases should be synchronized unless the firmware plays with them > (assuming the HRESET pins are wired together). Certainly on my 7600 with a 2-cpu powersurge board, with the code that is currently in the devel kernel to use the tb register, you don't get the same time on both cpus. I haven't had a chance to look at your patch in detail yet, hopefully soon. At a quick glance it seemed to be touching a lot of stuff so it will take more than a quick glance. :-) Paul. -- Paul Mackerras, Senior Open Source Researcher, Linuxcare, Inc. +61 2 6262 8990 tel, +61 2 6262 8991 fax paulus@linuxcare.com.au, http://www.linuxcare.com.au/ Linuxcare. Support for the revolution. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-08 1:39 ` Paul Mackerras @ 2000-08-11 11:04 ` Gabriel Paubert 2000-08-12 6:29 ` Paul Mackerras 0 siblings, 1 reply; 63+ messages in thread From: Gabriel Paubert @ 2000-08-11 11:04 UTC (permalink / raw) To: Paul Mackerras; +Cc: linuxppc-dev On Tue, 8 Aug 2000, Paul Mackerras wrote: > Gabriel Paubert writes: > > > Hard reset also clears the timebase on all the processors I know, so the > > time bases should be synchronized unless the firmware plays with them > > (assuming the HRESET pins are wired together). > > Certainly on my 7600 with a 2-cpu powersurge board, with the code that > is currently in the devel kernel to use the tb register, you don't get > the same time on both cpus. Yes, we need a way to check that the timebase are in sync and to sync them if they are not. That's basically the same problem in any case. The problem is to do it in a way that works on all machines... However current code is so broken that, if you had a jiffy counter per processor, you would see them drifting away. > I haven't had a chance to look at your patch in detail yet, hopefully > soon. At a quick glance it seemed to be touching a lot of stuff so it > will take more than a quick glance. :-) It does not toch so much when you look carefully at it, only timekeeping but it's basically an all or nothing (and some global variable name changes to be sure that I catch all the occurences which add somewhat to the patch size). However, I have still found bugs in my code (but it seems to be slowly converging). I'm also considering switching to BitKeeper tree, and sending these patches in smaller and more digestible chunks: - improved timing stability (fixed interrupt rate) - 601 support and faster gettimeofday (no divide anymore) - preliminary SMP support (gettimeofday still would have jiffy resolution on SMP) The problem is that these parts are somewhat hard to disentangle. I'm also already running 2.4.0-test6 from kernel.org which was not yet merged in the BK tree a few hours ago and that includes a few things that I need. Regards, Gabriel ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-11 11:04 ` Gabriel Paubert @ 2000-08-12 6:29 ` Paul Mackerras 2000-08-12 12:02 ` Ethan Benson ` (2 more replies) 0 siblings, 3 replies; 63+ messages in thread From: Paul Mackerras @ 2000-08-12 6:29 UTC (permalink / raw) To: Gabriel Paubert; +Cc: linuxppc-dev Gabriel Paubert writes: > > Certainly on my 7600 with a 2-cpu powersurge board, with the code that > > is currently in the devel kernel to use the tb register, you don't get > > the same time on both cpus. > > Yes, we need a way to check that the timebase are in sync and to sync > them if they are not. That's basically the same problem in any case. > The problem is to do it in a way that works on all machines... Until we get SMP working on the 2-cpu G4 machines (hopefully I will be getting one soon), the old powersurge board is the only supported SMP powermac. I found with mine that when you start the second CPU, it stops the decrementers (and I expect timebases as well) on both CPUs until you send an interrupt from the primary to the secondary cpu. So on this platform at least, we can get the decrementers and timebases synchronized. > It does not toch so much when you look carefully at it, only timekeeping > but it's basically an all or nothing (and some global variable name > changes to be sure that I catch all the occurences which add somewhat to > the patch size). I merged in your patch and tried it on my 7600/powersurge machine. It seems to work just fine. > I have still found bugs in my code (but it seems to be slowly converging). > I'm also considering switching to BitKeeper tree, and sending these > patches in smaller and more digestible chunks: I'm going to try to update the linuxppc_2_3 bitkeeper tree to -test6, since Cort is busy moving at the moment. In the meantime I will update the rsync tree at linuxcare.com.au::linux-pmac-devel with your patch shortly. The get/set rtc stuff on powermac still needs work. IMHO the way it should work on powermacs is this: - at boot, read the RTC and the xpram and apply the correction from the xpram - /dev/rtc reads and writes the RTC value directly (no timezone correction) - if the RTC is updated from other places in the kernel, read the timezone recorded in xpram and apply that correction before writing it to the RTC. Paul. -- Paul Mackerras, Senior Open Source Researcher, Linuxcare, Inc. +61 2 6262 8990 tel, +61 2 6262 8991 fax paulus@linuxcare.com.au, http://www.linuxcare.com.au/ Linuxcare. Support for the revolution. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-12 6:29 ` Paul Mackerras @ 2000-08-12 12:02 ` Ethan Benson 2000-08-12 12:51 ` Gabriel Paubert 2000-08-12 18:46 ` Gabriel Paubert 2000-08-14 12:59 ` Gabriel Paubert 2 siblings, 1 reply; 63+ messages in thread From: Ethan Benson @ 2000-08-12 12:02 UTC (permalink / raw) To: Paul Mackerras; +Cc: Gabriel Paubert, linuxppc-dev [-- Attachment #1: Type: text/plain, Size: 659 bytes --] On Sat, Aug 12, 2000 at 04:29:12PM +1000, Paul Mackerras wrote: > > The get/set rtc stuff on powermac still needs work. IMHO the way it > should work on powermacs is this: > > - at boot, read the RTC and the xpram and apply the correction from > the xpram > > - /dev/rtc reads and writes the RTC value directly (no timezone > correction) > > - if the RTC is updated from other places in the kernel, read the > timezone recorded in xpram and apply that correction before writing > it to the RTC. would this still allow for rtc in UTC? for those of us who do not use MacOS.. -- Ethan Benson http://www.alaska.net/~erbenson/ [-- Attachment #2: Type: application/pgp-signature, Size: 0 bytes --] ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-12 12:02 ` Ethan Benson @ 2000-08-12 12:51 ` Gabriel Paubert 0 siblings, 0 replies; 63+ messages in thread From: Gabriel Paubert @ 2000-08-12 12:51 UTC (permalink / raw) To: Ethan Benson; +Cc: Paul Mackerras, linuxppc-dev On Sat, 12 Aug 2000, Ethan Benson wrote: > On Sat, Aug 12, 2000 at 04:29:12PM +1000, Paul Mackerras wrote: > > > > The get/set rtc stuff on powermac still needs work. IMHO the way it > > should work on powermacs is this: > > > > - at boot, read the RTC and the xpram and apply the correction from > > the xpram > > > > - /dev/rtc reads and writes the RTC value directly (no timezone > > correction) > > > > - if the RTC is updated from other places in the kernel, read the > > timezone recorded in xpram and apply that correction before writing > > it to the RTC. > > would this still allow for rtc in UTC? for those of us who do not use MacOS.. Of course, at least that's how I see it. Just set all the xpram clock variables to zero. BTW, if MacOS X claims to be a true Unix, it should also support it. Gabriel. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-12 6:29 ` Paul Mackerras 2000-08-12 12:02 ` Ethan Benson @ 2000-08-12 18:46 ` Gabriel Paubert 2000-08-14 12:59 ` Gabriel Paubert 2 siblings, 0 replies; 63+ messages in thread From: Gabriel Paubert @ 2000-08-12 18:46 UTC (permalink / raw) To: Paul Mackerras; +Cc: linuxppc-dev On Sat, 12 Aug 2000, Paul Mackerras wrote: > Gabriel Paubert writes: > > > > Certainly on my 7600 with a 2-cpu powersurge board, with the code that > > > is currently in the devel kernel to use the tb register, you don't get > > > the same time on both cpus. > > > > Yes, we need a way to check that the timebase are in sync and to sync > > them if they are not. That's basically the same problem in any case. > > The problem is to do it in a way that works on all machines... > > Until we get SMP working on the 2-cpu G4 machines (hopefully I will be > getting one soon), the old powersurge board is the only supported SMP > powermac. I found with mine that when you start the second CPU, it > stops the decrementers (and I expect timebases as well) on both CPUs > until you send an interrupt from the primary to the secondary cpu. I've just tested on my machines since it was not clear to me that the TBEN pin would stop the decrementer or not: it does. It is the only way I know to stop the timebase (besides stopping the clock that is). There may still be issues with the ordering of time_init and starting the second processor. We'll see... > So on this platform at least, we can get the decrementers and > timebases synchronized. The only important registers are the timebases. First my patch got rid of the gross `while (get_dec() == dval);' loop, which did not work properly in any case. Depending on cache misses and external influences between this loop and the setting of the decrementer, I got effective jiffy frequency varying by 20ppm or so (that's about 200ns per 10 ms). This had very nasty consequences even on my stratum 1 NTP server (just compiling a kernel would make the clock drift by several milliseconds before the PLL would react) on SMP this would have meant that the timer interrupts would have been drifting away randomly from each other. The solution I implemented is simple: use the time base as a reference and generate a decrementer interrupt every n ticks of the timebase, even if the 601 makes things more complex (the code in the patch I sent is still wrong for 601, an improved one is coming soon). > I merged in your patch and tried it on my 7600/powersurge machine. It > seems to work just fine. So are the timebases in sync ? I was preparing a patch which should work even with unsynced timebases, but then gettimeofday can only have jiffy resolution. Beware that my next patch might break it, however, but it's the fun of writing code that you can't test yourself :-) > > I have still found bugs in my code (but it seems to be slowly converging). > > I'm also considering switching to BitKeeper tree, and sending these > > patches in smaller and more digestible chunks: > > I'm going to try to update the linuxppc_2_3 bitkeeper tree to -test6, > since Cort is busy moving at the moment. In the meantime I will > update the rsync tree at linuxcare.com.au::linux-pmac-devel with your > patch shortly. I tried once to download your tree, but bandwidth to autralia is too small from here. > The get/set rtc stuff on powermac still needs work. IMHO the way it > should work on powermacs is this: > > - at boot, read the RTC and the xpram and apply the correction from > the xpram Yes for PMAC. Apply the correction later (or never) for other machines. BTW, man setttimeofday is very interesting about dst: The field tz_dsttime contains a symbolic constant (values are given below) that indicates in which part of the year Daylight Saving Time is in force. (Note: its value is con- stant throughout the year - it does not indicate that DST is in force, it just selects an algorithm.) The daylight saving time algorithms defined are as follows : DST_NONE /* not on dst */ DST_USA /* USA style dst */ DST_AUST /* Australian style dst */ DST_WET /* Western European dst */ DST_MET /* Middle European dst */ DST_EET /* Eastern European dst */ DST_CAN /* Canada */ DST_GB /* Great Britain and Eire */ DST_RUM /* Rumania */ DST_TUR /* Turkey */ DST_AUSTALT /* Australian style with shift in 1986 */ Of course it turned out that the period in which Daylight Saving Time is in force cannot be given by a simple algo- rithm, one per country; indeed, this period is determined by unpredictable political decisions. So this method of representing time zones has been abandoned. Under Linux, in a call to settimeofday the tz_dsttime field should be zero. So you might have to find another way to pass the dst field. > - /dev/rtc reads and writes the RTC value directly (no timezone > correction) Right, note that there is a problem in get_rtc_time for some machines, if we want this function to be used for the /dev/rtc driver, it should not wait for the second boundary to return, or you can force one second busy wait loop in the kernel by reading /dev/rtc which opens the doors to interesting attacks ;-) The right place to put this waiting loop is in time_init, supposing that pmac_read_rtc through cuda or pmu does not wait for a second boundary. I'm currently working on this, but I don't plan to update the code for all machines: only PreP, CHRP and PMAC. This should provide enough examples to apply to the other machines (which won't compile anyway due to deliberate global variable name changes). The maintainers of other machines can contact me if they need any help... > > - if the RTC is updated from other places in the kernel, read the > timezone recorded in xpram and apply that correction before writing > it to the RTC. Ok, fine for pmac. For other platforms I shall need a way to round to the closest half hour before writing the clock when the NTP PLL is closed (which is basically the only kernel part which updates the clock). This will not yet be in the next patch set. Regards, Gabriel ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-12 6:29 ` Paul Mackerras 2000-08-12 12:02 ` Ethan Benson 2000-08-12 18:46 ` Gabriel Paubert @ 2000-08-14 12:59 ` Gabriel Paubert 2 siblings, 0 replies; 63+ messages in thread From: Gabriel Paubert @ 2000-08-14 12:59 UTC (permalink / raw) To: Paul Mackerras; +Cc: linuxppc-dev On Sat, 12 Aug 2000, Paul Mackerras wrote: > I merged in your patch and tried it on my 7600/powersurge machine. It > seems to work just fine. Here is the first followup patch, which needs testing, to be applied on top of the preceding one. This patch corrects 601 handling, cleans up many other small things, should ensure that no decrementer interrupt is ever lost on SMP and UP (unless blocked for >1s on 601 or 2^32 TB ticks on others), and moves the initial time read loop in some get_rtc_time functions to time_init. Precision on boot still has to be checked. Booted on an MVME2600... I'm not going to have time to switch to BK before end of September. Time handling still needs more cleanups, I hope to do some in the next 2 weeks but I'm very busy on other fronts. Gabriel. arch/ppc/kernel/chrp_time.c | 26 +++++---- arch/ppc/kernel/pmac_time.c | 4 - arch/ppc/kernel/prep_setup.c | 48 +++++++++------- arch/ppc/kernel/prep_time.c | 44 +++++---------- arch/ppc/kernel/time.c | 122 ++++++++++++++++++++++++++++++------------- include/asm-ppc/hardirq.h | 7 ++ 6 files changed, 155 insertions, 96 deletions diff -Nru a/arch/ppc/kernel/chrp_time.c b/arch/ppc/kernel/chrp_time.c --- a/arch/ppc/kernel/chrp_time.c Mon Aug 14 14:48:34 2000 +++ b/arch/ppc/kernel/chrp_time.c Mon Aug 14 14:48:34 2000 @@ -115,28 +115,34 @@ unsigned long __chrp chrp_get_rtc_time(void) { unsigned int year, mon, day, hour, min, sec; - int i; + int uip, i; /* The Linux interpretation of the CMOS clock register contents: * When the Update-In-Progress (UIP) flag goes from 1 to 0, the * RTC registers show the second which has precisely just started. * Let's hope other operating systems interpret the RTC the same way. */ - /* read RTC exactly on falling edge of update flag */ - for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */ - if (chrp_cmos_clock_read(RTC_FREQ_SELECT) & RTC_UIP) - break; - for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */ - if (!(chrp_cmos_clock_read(RTC_FREQ_SELECT) & RTC_UIP)) - break; - do { /* Isn't this overkill ? UIP above should guarantee consistency */ + + /* Since the UIP flag is set for about 2.2 ms and the clock + * is typically written with a precision of 1 jiffy, trying + * to obtain a precision better than a few milliseconds is + * an illusion. Only consistency is interesting, this also + * allows to use the routine for /dev/rtc without a potential + * 1 second kernel busy loop triggered by any reader of /dev/rtc. + */ + + for ( i = 0; i<1000000; i++) { + uip = chrp_cmos_clock_read(RTC_FREQ_SELECT); sec = chrp_cmos_clock_read(RTC_SECONDS); min = chrp_cmos_clock_read(RTC_MINUTES); hour = chrp_cmos_clock_read(RTC_HOURS); day = chrp_cmos_clock_read(RTC_DAY_OF_MONTH); mon = chrp_cmos_clock_read(RTC_MONTH); year = chrp_cmos_clock_read(RTC_YEAR); - } while (sec != chrp_cmos_clock_read(RTC_SECONDS)); + uip |= chrp_cmos_clock_read(RTC_FREQ_SELECT); + if ((uip & RTC_UIP)==0) break; + } + if (!(chrp_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { BCD_TO_BIN(sec); diff -Nru a/arch/ppc/kernel/pmac_time.c b/arch/ppc/kernel/pmac_time.c --- a/arch/ppc/kernel/pmac_time.c Mon Aug 14 14:48:34 2000 +++ b/arch/ppc/kernel/pmac_time.c Mon Aug 14 14:48:34 2000 @@ -219,8 +219,8 @@ write_lock_irqsave(&xtime_lock, flags); xtime.tv_sec = pmac_get_rtc_time() + time_diff; set_dec(tb_ticks_per_jiffy); - /* No PBOOK has a 601 AFAIK, so use get_tbl not binary_tbl */ - tb_last_stamp=get_tbl(); + /* No PBOOK has a 601 AFAIK, so use get_tbl, not native */ + last_jiffy_stamp(0)=tb_last_stamp=get_tbl(); xtime.tv_usec = 0; last_rtc_update = xtime.tv_sec; write_unlock_irqrestore(&xtime_lock, flags); diff -Nru a/arch/ppc/kernel/prep_setup.c b/arch/ppc/kernel/prep_setup.c --- a/arch/ppc/kernel/prep_setup.c Mon Aug 14 14:48:34 2000 +++ b/arch/ppc/kernel/prep_setup.c Mon Aug 14 14:48:34 2000 @@ -442,37 +442,41 @@ free_irq( 0, NULL); } +static void __init mk48t59_init(void) { + unsigned char tmp; -/* We use the NVRAM RTC to time a second to calibrate the decrementer. */ + tmp = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLB); + if (tmp & MK48T59_RTC_CB_STOP) { + printk("Warning: RTC was stopped, date will be wrong.\n"); + ppc_md.nvram_write_val(MK48T59_RTC_CONTROLB, + tmp & ~MK48T59_RTC_CB_STOP); + /* Low frequency crystal oscillators may take a very long + * time to startup and stabilize. For now just ignore the + * the issue, but attempting to calibrate the decrementer + * from the RTC just after this wakeup is likely to be very + * inaccurate. Firmware should not allow to load + * the OS with the clock stopped anyway... + */ + } + /* Ensure that the clock registers are updated */ + tmp = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA); + tmp &= ~(MK48T59_RTC_CA_READ | MK48T59_RTC_CA_WRITE); + ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, tmp); +} + +/* We use the NVRAM RTC to time a second to calibrate the decrementer, + * the RTC registers have just been set up in the right state by the + * preceding routine. + */ void __init mk48t59_calibrate_decr(void) { unsigned long freq; unsigned long t1; - unsigned char save_control; long i; unsigned char sec; - - /* Make sure the time is not stopped. */ - save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLB); - - ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, - (save_control & (~MK48T59_RTC_CB_STOP))); - - /* Now make sure the read bit is off so the value will change. */ - save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA); - save_control &= ~MK48T59_RTC_CA_READ; - ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control); - - /* Read the seconds value to see when it changes. */ sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS); - /* Actually this is bad for precicion, we should have a loop in - * which we only read the seconds counter. nvram_read_val writes - * the address bytes on every call and this takes a lot of time. - * Perhaps an nvram_wait_change method returning a time - * stamp with a loop count as parameter would be the solution. - */ for (i = 0 ; i < 1000000 ; i++) { /* may take up to 1 second... */ t1 = get_tbl(); if (ppc_md.nvram_read_val(MK48T59_RTC_SECONDS) != sec) { @@ -805,6 +809,7 @@ { ppc_md.set_rtc_time = mk48t59_set_rtc_time; ppc_md.get_rtc_time = mk48t59_get_rtc_time; + ppc_md.time_init = mk48t59_init; } else { @@ -825,6 +830,7 @@ ppc_md.set_rtc_time = mk48t59_set_rtc_time; ppc_md.get_rtc_time = mk48t59_get_rtc_time; ppc_md.calibrate_decr = mk48t59_calibrate_decr; + ppc_md.time_init = mk48t59_init; } #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) diff -Nru a/arch/ppc/kernel/prep_time.c b/arch/ppc/kernel/prep_time.c --- a/arch/ppc/kernel/prep_time.c Mon Aug 14 14:48:34 2000 +++ b/arch/ppc/kernel/prep_time.c Mon Aug 14 14:48:34 2000 @@ -99,28 +99,34 @@ unsigned long mc146818_get_rtc_time(void) { unsigned int year, mon, day, hour, min, sec; - int i; + int uip, i; /* The Linux interpretation of the CMOS clock register contents: * When the Update-In-Progress (UIP) flag goes from 1 to 0, the * RTC registers show the second which has precisely just started. * Let's hope other operating systems interpret the RTC the same way. */ - /* read RTC exactly on falling edge of update flag */ - for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */ - if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) - break; - for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */ - if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) - break; - do { /* Isn't this overkill ? UIP above should guarantee consistency */ + + /* Since the UIP flag is set for about 2.2 ms and the clock + * is typically written with a precision of 1 jiffy, trying + * to obtain a precision better than a few milliseconds is + * an illusion. Only consistency is interesting, this also + * allows to use the routine for /dev/rtc without a potential + * 1 second kernel busy loop triggered by any reader of /dev/rtc. + */ + + for ( i = 0; i<1000000; i++) { + uip = CMOS_READ(RTC_FREQ_SELECT); sec = CMOS_READ(RTC_SECONDS); min = CMOS_READ(RTC_MINUTES); hour = CMOS_READ(RTC_HOURS); day = CMOS_READ(RTC_DAY_OF_MONTH); mon = CMOS_READ(RTC_MONTH); year = CMOS_READ(RTC_YEAR); - } while (sec != CMOS_READ(RTC_SECONDS)); + uip |= CMOS_READ(RTC_FREQ_SELECT); + if ((uip & RTC_UIP)==0) break; + } + if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { @@ -179,26 +185,10 @@ unsigned int year, mon, day, hour, min, sec; int i; - /* Make sure the time is not stopped. */ - save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLB); - - ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, - (save_control & (~MK48T59_RTC_CB_STOP))); - - /* Now make sure the read bit is off so the value will change. */ + /* Simple: freeze the clock, read it and allow updates again */ save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA); save_control &= ~MK48T59_RTC_CA_READ; ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control); - - /* Read the seconds value to see when it changes. */ - sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS); - - /* Wait until the seconds value changes, then read the value. */ - for (i = 0 ; i < 1000000 ; i++) { /* may take up to 1 second... */ - if (ppc_md.nvram_read_val(MK48T59_RTC_SECONDS) != sec) { - break; - } - } /* Set the register to read the value. */ ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, diff -Nru a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c --- a/arch/ppc/kernel/time.c Mon Aug 14 14:48:34 2000 +++ b/arch/ppc/kernel/time.c Mon Aug 14 14:48:34 2000 @@ -81,6 +81,19 @@ unsigned tb_last_stamp; extern unsigned long wall_jiffies; + +/* Timer interrupt helper function */ +static inline int tb_delta(unsigned *jiffy_stamp) { + int delta; + if (__USE_RTC()) { + delta = get_rtcl(); + if (delta < *jiffy_stamp) *jiffy_stamp -= 1000000000; + delta -= *jiffy_stamp; + } else { + delta = get_tbl() - *jiffy_stamp; + } + return delta; +} /* * timer_interrupt - gets called when the decrementer overflows, * with interrupts disabled. @@ -88,9 +101,9 @@ */ int timer_interrupt(struct pt_regs * regs) { - int delta; - unsigned local_stamp = tb_last_stamp; + int next_dec; unsigned long cpu = smp_processor_id(); + unsigned jiffy_stamp = last_jiffy_stamp(cpu); hardirq_enter(cpu); #ifdef CONFIG_SMP @@ -114,17 +127,12 @@ } #endif /* CONFIG_SMP */ - /* This might fail on 601 SMP systems, are there any out there ? - * The right way to do it might be to add a per CPU timebase stamp - * in the per CPU interrupt structure. Would this be acceptable ? - */ - while ((delta = tb_ticks_per_jiffy-tb_ticks_since(local_stamp)) <=0) { - - local_stamp += tb_ticks_per_jiffy; + do { + jiffy_stamp += tb_ticks_per_jiffy; if (smp_processor_id()) continue; /* We are in an interrupt, no need to save/restore flags */ write_lock(&xtime_lock); - tb_last_stamp = local_stamp; + tb_last_stamp = jiffy_stamp; do_timer(regs); /* * update the rtc when needed, this should be performed on the @@ -137,14 +145,14 @@ * timer interrupt resolution and possible delay, but here we * hit a quantization limit which can only be solved by higher * resolution timers and decoupling time management from timer - * interrupts. + * interrupts. This is also wrong on the clocks + * which require being written at the half second boundary. * We should have an rtc call that only sets the minutes and * seconds like on Intel to avoid problems with non UTC clocks. */ if ( (time_status & STA_UNSYNC) == 0 && xtime.tv_sec - last_rtc_update >= 659 && - xtime.tv_usec >= 1000000 - 1500000/HZ && - xtime.tv_usec <= 1000000 - 500000/HZ && + abs(xtime.tv_usec - (1000000-1000000/HZ)) < 500000/HZ && jiffies-wall_jiffies == 1) { if (ppc_md.set_rtc_time(xtime.tv_sec+1) == 0) last_rtc_update = xtime.tv_sec+1; @@ -153,8 +161,9 @@ last_rtc_update += 60; } write_unlock(&xtime_lock); - } - set_dec(delta); + } while((next_dec=tb_ticks_per_jiffy-tb_delta(&jiffy_stamp))<0); + set_dec(next_dec); + last_jiffy_stamp(cpu) = jiffy_stamp; #ifdef CONFIG_SMP smp_local_timer_interrupt(regs); #endif @@ -177,7 +186,14 @@ read_lock_irqsave(&xtime_lock, flags); sec = xtime.tv_sec; usec = xtime.tv_usec; +#ifdef CONFIG_SMP + /* As long as timebases are not in sync, gettimeofday can only + * have jiffy resolution on SMP. + */ + delta = 0; +#else delta = tb_ticks_since(tb_last_stamp); +#endif lost_ticks = jiffies-wall_jiffies; read_unlock_irqrestore(&xtime_lock, flags); @@ -193,15 +209,18 @@ void do_settimeofday(struct timeval *tv) { unsigned long flags; - int tv_delta; + int tb_delta, new_usec, new_sec; write_lock_irqsave(&xtime_lock, flags); - /* the rtc has to be updated soon but *not* *now* to avoid - * introducing random fractional second offsets. Do not attempt the - * update before the next second boundary. Actually, it will not - * be updated until STA_UNSYNC is cleared. Note also that + /* Updating the RTC is not the job of this code. If the time is + * stepped under NTP, the RTC will be update after STA_UNSYNC + * is cleared. Tool like clock/hwclock either copy the RTC + * to the system time, in which case there is no point in writing + * to the RTC again, or write to the RTC but then they don't call + * settimeofday to perform this operation. Note also that * we don't touch the decrementer since: * a) it would lose timer interrupt synchronization on SMP + * (if it is working one day) * b) it could make one jiffy spuriously shorter or longer * which would introduce another source of uncertainty potentially * harmful to relatively short timers. @@ -210,12 +229,26 @@ * is not always a multiple of 1/Hz seconds. */ - tv_delta = mulhwu(tb_to_us, tb_ticks_since(tb_last_stamp)); - xtime.tv_sec = tv->tv_sec - ((tv_delta>tv->tv_usec) ? 1 : 0); - xtime.tv_usec = tv->tv_usec + ((tv_delta>tv->tv_usec) ? - 1000000 : 0) - tv_delta; - last_rtc_update = xtime.tv_sec - 658; - + /* This works perfectly on SMP only if the tb are in sync but + * guarantees an error < 1 jiffy even if they are off by eons, + * still reasonable when gettimeofday resolution is 1 jiffy. + */ + tb_delta = tb_ticks_since(last_jiffy_stamp(smp_processor_id())); + tb_delta += (jiffies-wall_jiffies) * tb_ticks_per_jiffy; + new_sec = tv->tv_sec; + new_usec = tv->tv_usec - mulhwu(tb_to_us, tb_delta); + while (new_usec <0) { + new_sec--; + new_usec += 1000000; + } + xtime.tv_usec = new_usec; + xtime.tv_sec = new_sec; + + /* In case of a large backwards jump in time with NTP, we want the + * clock to be updated as soon as the PLL is again in lock. + */ + last_rtc_update = new_sec - 658; + time_adjust = 0; /* stop active adjtime() */ time_status |= STA_UNSYNC; time_state = TIME_ERROR; /* p. 24, (a) */ @@ -227,6 +260,9 @@ void __init time_init(void) { + time_t sec, old_sec; + unsigned old_stamp, stamp, elapsed; + /* This function is only called on the boot processor */ unsigned long flags; if (ppc_md.time_init != NULL) { @@ -238,18 +274,38 @@ tb_ticks_per_jiffy = DECREMENTER_COUNT_601; /* mulhwu_scale_factor(1000000000, 1000000) is 0x418937 */ tb_to_us = 0x418937; - } else if (!smp_processor_id()) { + } else { ppc_md.calibrate_decr(); } + /* Now that the decrementer is calibrated, it can be used in case the + * clock is stuck, but the fact that we have to handle the 601 + * makes things more complex. Repeatedly read the RTC until the + * next second boundary to try to achieve some precision... + */ + stamp = get_native_tbl(); + sec = ppc_md.get_rtc_time(); + elapsed = 0; + do { + old_stamp = stamp; + old_sec = sec; + stamp = get_native_tbl(); + if (__USE_RTC() && stamp < old_stamp) old_stamp -= 1000000000; + elapsed += stamp - old_stamp; + sec = ppc_md.get_rtc_time(); + } while ( sec == old_sec && elapsed < 2*HZ*tb_ticks_per_jiffy); + if (sec==old_sec) { + printk("Warning: real time clock seems stuck!\n"); + } write_lock_irqsave(&xtime_lock, flags); - xtime.tv_sec = ppc_md.get_rtc_time(); - tb_last_stamp = get_native_tbl(); - set_dec(tb_ticks_per_jiffy); + xtime.tv_sec = sec; + last_jiffy_stamp(0) = tb_last_stamp = stamp; xtime.tv_usec = 0; /* No update now, we just read the time from the RTC ! */ last_rtc_update = xtime.tv_sec; write_unlock_irqrestore(&xtime_lock, flags); + /* Not exact, but the timer interrupt takes care of this */ + set_dec(tb_ticks_per_jiffy); } /* Converts Gregorian date to seconds since 1970-01-01 00:00:00. @@ -396,12 +452,6 @@ * the returned value will be zero. * Many corner cases have been checked and seem to work, * some might have been forgotten in the test however. - * The precision for typical values (outscale is 1 million), - * inscale is between a few millions to a few tens of - * millions is 27-28 bits, which is optimistic about the - * quality of 99.99% CPU clock oscillators (and the precision - * with which the frequency is measured at boot with the current - * setup) but does no harm. */ err = inscale*(mlt+1); if (err <= inscale/2) mlt++; diff -Nru a/include/asm-ppc/hardirq.h b/include/asm-ppc/hardirq.h --- a/include/asm-ppc/hardirq.h Mon Aug 14 14:48:34 2000 +++ b/include/asm-ppc/hardirq.h Mon Aug 14 14:48:34 2000 @@ -5,16 +5,23 @@ #include <asm/smp.h> /* entry.S is sensitive to the offsets of these fields */ +/* The __last_jiffy_stamp field is needed to ensure that no decrementer + * interrupt is lost on SMP machines. Since on most CPUs it is in the same + * cache line as local_irq_count, it is cheap to access and is also used on UP + * for uniformity. + */ typedef struct { unsigned int __softirq_active; unsigned int __softirq_mask; unsigned int __local_irq_count; unsigned int __local_bh_count; unsigned int __syscall_count; + unsigned int __last_jiffy_stamp; } ____cacheline_aligned irq_cpustat_t; #include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ +#define last_jiffy_stamp(cpu) __IRQ_STAT((cpu), __last_jiffy_stamp) /* * Are we in an interrupt context? Either doing bottom half * or hardware interrupt processing? ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
[parent not found: <Pine.LNX.3.96LJ1.1b7.1000803182949.650C-100000@ofey.earthl ink.net>]
* Re: rtc again... [not found] ` <Pine.LNX.3.96LJ1.1b7.1000803182949.650C-100000@ofey.earthl ink.net> @ 2000-08-03 23:58 ` Franz Sirl 2000-08-04 0:33 ` Takashi Oe 0 siblings, 1 reply; 63+ messages in thread From: Franz Sirl @ 2000-08-03 23:58 UTC (permalink / raw) To: Takashi Oe Cc: Gabriel Paubert, Benjamin Herrenschmidt, Martin Costabel, linuxppc-dev, Iain Sandoe At 01:33 04.08.00, Takashi Oe wrote: >On Thu, 3 Aug 2000, Gabriel Paubert wrote: > > > ===== arch/ppc/kernel/pmac_time.c 1.2 vs 1.5 ===== > > --- 1.2/arch/ppc/kernel/pmac_time.c Mon Jun 19 19:59:36 2000 > > +++ 1.5/arch/ppc/kernel/pmac_time.c Mon Jul 31 11:28:27 2000 >[...] > > int pmac_set_rtc_time(unsigned long nowtime) > > { > > - return 0; > > +#ifdef CONFIG_ADB > > + struct adb_request req; > > +#endif > > + nowtime += RTC_OFFSET - sys_tz.tz_minuteswest * 60; > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ >This needs to be changed to > >+ nowtime += RTC_OFFSET - sys_tz.tz_minuteswest * 60 + >(sys_tz.tz_dsttime? 3600: 0); No, don't handle DST in the kernel!! hwclock handles this in userland, see the hwclock source for details. Franz. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-03 23:58 ` Franz Sirl @ 2000-08-04 0:33 ` Takashi Oe 2000-08-04 12:54 ` Benjamin Herrenschmidt 0 siblings, 1 reply; 63+ messages in thread From: Takashi Oe @ 2000-08-04 0:33 UTC (permalink / raw) To: Franz Sirl Cc: Gabriel Paubert, Benjamin Herrenschmidt, Martin Costabel, linuxppc-dev, Iain Sandoe On Fri, 4 Aug 2000, Franz Sirl wrote: > At 01:33 04.08.00, Takashi Oe wrote: > > >On Thu, 3 Aug 2000, Gabriel Paubert wrote: > > > > > ===== arch/ppc/kernel/pmac_time.c 1.2 vs 1.5 ===== > > > --- 1.2/arch/ppc/kernel/pmac_time.c Mon Jun 19 19:59:36 2000 > > > +++ 1.5/arch/ppc/kernel/pmac_time.c Mon Jul 31 11:28:27 2000 > >[...] > > > int pmac_set_rtc_time(unsigned long nowtime) > > > { > > > - return 0; > > > +#ifdef CONFIG_ADB > > > + struct adb_request req; > > > +#endif > > > + nowtime += RTC_OFFSET - sys_tz.tz_minuteswest * 60; > > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > >This needs to be changed to > > > >+ nowtime += RTC_OFFSET - sys_tz.tz_minuteswest * 60 + > >(sys_tz.tz_dsttime? 3600: 0); > > No, don't handle DST in the kernel!! hwclock handles this in userland, see > the hwclock source for details. Oh, "nowtime" is UTC + DST fix up then??? If so, that seems to be broken to me. Takashi Oe ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-04 0:33 ` Takashi Oe @ 2000-08-04 12:54 ` Benjamin Herrenschmidt 2000-08-04 13:40 ` Takashi Oe 0 siblings, 1 reply; 63+ messages in thread From: Benjamin Herrenschmidt @ 2000-08-04 12:54 UTC (permalink / raw) To: Takashi Oe, linuxppc-dev > >Oh, "nowtime" is UTC + DST fix up then??? If so, that seems to be broken >to me AFAIK, the timezone offset in nvram includes the DST fixup. Ben. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-04 12:54 ` Benjamin Herrenschmidt @ 2000-08-04 13:40 ` Takashi Oe 0 siblings, 0 replies; 63+ messages in thread From: Takashi Oe @ 2000-08-04 13:40 UTC (permalink / raw) To: Benjamin Herrenschmidt; +Cc: linuxppc-dev On Fri, 4 Aug 2000, Benjamin Herrenschmidt wrote: > > > >Oh, "nowtime" is UTC + DST fix up then??? If so, that seems to be broken > >to me > > AFAIK, the timezone offset in nvram includes the DST fixup. Yes, that's right. My assumption was "nowtime" given to kernel for pmac_set_rtc_time() is UTC. If that's the case, the following code in pmac_set_rtc_time() nowtime += RTC_OFFSET - sys_tz.tz_minuteswest * 60; is incomplete because it does not include DST fix up and the time stored via CUDA or PMU will be an hour off from localtime which Mac OS uses during DST is in effect. Is my assumption correct? What I was saying is that if "nowtime" given to kernel is neither UTC or localtime, the interface seems to be broken (to me). Takashi Oe ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-03 10:54 ` Gabriel Paubert ` (2 preceding siblings ...) [not found] ` <Pine.LNX.3.96LJ1.1b7.1000803182949.650C-100000@ofey.earthl ink.net> @ 2000-08-04 13:20 ` Geert Uytterhoeven 2000-08-08 11:20 ` Gabriel Paubert 3 siblings, 1 reply; 63+ messages in thread From: Geert Uytterhoeven @ 2000-08-04 13:20 UTC (permalink / raw) To: Gabriel Paubert Cc: Benjamin Herrenschmidt, Martin Costabel, linuxppc-dev, Iain Sandoe On Thu, 3 Aug 2000, Gabriel Paubert wrote: > On Thu, 3 Aug 2000, Benjamin Herrenschmidt wrote: > > >I am using it as module both for 2.2.17-bk and for 2.4.0-test5. They > > >don't give the same time, and I think it is the one in 2.4.0 that is > > >right. I am at GMT+2:00, and the time in 2.2.17 is 2 hours early. When I > > >change /etc/sysconfig/clock from "UTC=false" to "UTC=true", both times > > >shift by 2 hours, but the discrepancy remains. > > > > > >The following patch for bitkeeper linuxppc_2_2 fixes this problem for > > >me. It brings 2.2.17pre13 in line with 2.4.0-test5 (and MacOS). I cannot > > >test the VIAPMU part, so maybe there the offset is necessary, but for > > >the VIACUDA part, it seems wrong. > > > > You patch reverts a fix I made some time ago. Basially, what probably > > happens is that your RTC is in UTC time, not in local time. The Mac RTC > > is supposed to be in local time, the offset corrects the kernel time on > > boot to account for this. Previously, without that fix, the kernel used > > to boot with a bogus UTC time until userland fixes it. > > Actually given the problems with RTC being UTC or local time, the offset > might perhaps better be setup as a kernel parameter so that th system > start up in a known good state. It seems that it is in RAM for Macs, but > what about other machines (I have no problems since all my machines are > UTC and I simply refuse to use an OS which requires anything else) ? Why do you want to handle the offset in the kernel??? Any decent distro (e.g. Debian) allows to configure the time system for a hardware clock running in either UTC or local time, so the correction will be done on boot up. Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-04 13:20 ` Geert Uytterhoeven @ 2000-08-08 11:20 ` Gabriel Paubert 0 siblings, 0 replies; 63+ messages in thread From: Gabriel Paubert @ 2000-08-08 11:20 UTC (permalink / raw) To: Geert Uytterhoeven Cc: Benjamin Herrenschmidt, Martin Costabel, linuxppc-dev, Iain Sandoe Hi Geert, On Fri, 4 Aug 2000, Geert Uytterhoeven wrote: > > Actually given the problems with RTC being UTC or local time, the offset > > might perhaps better be setup as a kernel parameter so that th system > > start up in a known good state. It seems that it is in RAM for Macs, but > > what about other machines (I have no problems since all my machines are > > UTC and I simply refuse to use an OS which requires anything else) ? > > Why do you want to handle the offset in the kernel??? > > Any decent distro (e.g. Debian) allows to configure the time system for a > hardware clock running in either UTC or local time, so the correction will be > done on boot up. > I think there is some misunderstanding here. I don't want to handle the offset in the kernel, with one possible exception: when reading the RTC for the first time to initialize xtime. Getting timestamps right as early as possible might be important in some cases, and it's not a big deal since the code to do this is small and thrown away anyway. Oh and I can't remember whether the clock or hwclock command ever worked on my machines. I think hwclock did once upon a time; life is so much simpler with NTP anyway (but it is run quite late in the boot process, actually just before the rc.local script on most of my machines and after mounting NFS file systems and starting daemons like syslogd/crond/inetd). Gabriel. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: rtc again... 2000-08-03 9:00 ` Martin Costabel 2000-08-03 9:30 ` Benjamin Herrenschmidt @ 2000-08-03 10:31 ` Franz Sirl 1 sibling, 0 replies; 63+ messages in thread From: Franz Sirl @ 2000-08-03 10:31 UTC (permalink / raw) To: Martin Costabel; +Cc: linuxppc-dev, Iain Sandoe At 11:00 03.08.00, Martin Costabel wrote: >Iain Sandoe wrote: > > > > Hi, > > > > under 2.2.17pre15ben1 > > > > rtc does not give me the right answer when built in - what am I doing > wrong? > > > > It won't build load as a module right now 'cos I forgot to check ppc_ksyms > > before doing the build :-( .... (I remembered for 2.4.0). > > > > under 2.4.0-test5 it seems to be fine as a module (haven't tried built in). > >I am using it as module both for 2.2.17-bk and for 2.4.0-test5. They >don't give the same time, and I think it is the one in 2.4.0 that is >right. I am at GMT+2:00, and the time in 2.2.17 is 2 hours early. When I >change /etc/sysconfig/clock from "UTC=false" to "UTC=true", both times >shift by 2 hours, but the discrepancy remains. Are you sure you are using the "hwclock" utility coming with util-linux? And not the old pmac specific "clock" utility to query the clock? What happens if you remove all "clock" binaries from your system? Franz. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 63+ messages in thread
end of thread, other threads:[~2000-08-14 12:59 UTC | newest]
Thread overview: 63+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2000-08-08 11:35 rtc again Iain Sandoe
2000-08-08 13:14 ` Geert Uytterhoeven
-- strict thread matches above, loose matches on Subject: below --
2000-08-08 14:31 Iain Sandoe
2000-08-08 17:08 ` Michael Schmitz
2000-08-08 17:41 ` Benjamin Herrenschmidt
2000-08-08 22:44 ` Gabriel Paubert
2000-08-09 8:44 ` Benjamin Herrenschmidt
2000-08-09 11:32 ` Martin Costabel
2000-08-09 13:50 ` Gabriel Paubert
2000-08-09 15:25 ` Benjamin Herrenschmidt
2000-08-09 16:54 ` Takashi Oe
2000-08-09 17:04 ` Benjamin Herrenschmidt
2000-08-09 23:12 ` Takashi Oe
2000-08-09 23:48 ` Benjamin Herrenschmidt
2000-08-09 22:13 ` Gabriel Paubert
2000-08-09 22:48 ` Benjamin Herrenschmidt
2000-08-10 3:08 ` Gabriel Paubert
2000-08-10 0:00 ` William Blew
2000-08-09 14:26 ` Takashi Oe
2000-08-09 0:55 ` Takashi Oe
2000-08-09 8:48 ` Benjamin Herrenschmidt
2000-08-09 16:37 ` Takashi Oe
2000-08-09 22:46 ` Gabriel Paubert
2000-08-09 14:24 ` Geert Uytterhoeven
[not found] <20000804205524.383@192.168.1.10>
2000-08-05 1:10 ` Takashi Oe
2000-08-05 11:25 ` Benjamin Herrenschmidt
2000-08-05 14:44 ` Takashi Oe
2000-08-03 11:24 Iain Sandoe
2000-08-03 9:56 Iain Sandoe
2000-08-03 10:13 ` Benjamin Herrenschmidt
2000-08-03 11:58 ` Martin Costabel
2000-08-03 9:41 Iain Sandoe
2000-08-02 22:48 Iain Sandoe
2000-08-03 9:00 ` Martin Costabel
2000-08-03 9:30 ` Benjamin Herrenschmidt
2000-08-03 10:54 ` Gabriel Paubert
2000-08-03 11:14 ` Benjamin Herrenschmidt
2000-08-03 11:25 ` Gabriel Paubert
2000-08-03 11:45 ` Gabriel Paubert
2000-08-03 13:25 ` Benjamin Herrenschmidt
2000-08-03 23:33 ` Takashi Oe
2000-08-04 8:55 ` Gabriel Paubert
2000-08-04 15:25 ` David Edelsohn
2000-08-04 15:50 ` Benjamin Herrenschmidt
2000-08-07 12:33 ` Gabriel Paubert
2000-08-07 11:51 ` Gabriel Paubert
2000-08-07 13:18 ` Benjamin Herrenschmidt
2000-08-07 15:14 ` David Edelsohn
2000-08-07 21:16 ` Gabriel Paubert
2000-08-08 1:39 ` Paul Mackerras
2000-08-11 11:04 ` Gabriel Paubert
2000-08-12 6:29 ` Paul Mackerras
2000-08-12 12:02 ` Ethan Benson
2000-08-12 12:51 ` Gabriel Paubert
2000-08-12 18:46 ` Gabriel Paubert
2000-08-14 12:59 ` Gabriel Paubert
[not found] ` <Pine.LNX.3.96LJ1.1b7.1000803182949.650C-100000@ofey.earthl ink.net>
2000-08-03 23:58 ` Franz Sirl
2000-08-04 0:33 ` Takashi Oe
2000-08-04 12:54 ` Benjamin Herrenschmidt
2000-08-04 13:40 ` Takashi Oe
2000-08-04 13:20 ` Geert Uytterhoeven
2000-08-08 11:20 ` Gabriel Paubert
2000-08-03 10:31 ` Franz Sirl
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).