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/
From: Martin Costabel <hidden> Date: 2000-08-03 09:00:55
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
From: Benjamin Herrenschmidt <hidden> Date: 2000-08-03 09:30:49
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/
From: Franz Sirl <hidden> Date: 2000-08-03 10:31:16
At 11:00 03.08.00, Martin Costabel wrote:
Iain Sandoe wrote:
quoted
Hi,
under 2.2.17pre15ben1
rtc does not give me the right answer when built in - what am I doing
wrong?
quoted
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/
From: Gabriel Paubert <hidden> Date: 2000-08-03 10:54:28
On Thu, 3 Aug 2000, Benjamin Herrenschmidt wrote:
quoted
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 =====
@@ -304,7 +304,7 @@voidapus_calibrate_decr(void){#ifdef CONFIG_APUS-intfreq,divisor;+unsignedlongfreq;/* This algorithm for determining the bus speed wascontributedbyRalphSchmidt.*/
@@ -335,8 +335,8 @@bus_speed=60;freq=15000000;}elseif((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
@@ -164,8 +218,10 @@casePBOOK_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;
@@ -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=(unsignedlong*)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 =====
@@ -377,14 +377,13 @@*/void__initprep_res_calibrate_decr(void){-intfreq,divisor;+unsignedlongfreq,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 @@*butonprepwehavetofigureitout.*--Cort*/-intcalibrate_done=0;-volatileint*done_ptr=&calibrate_done;+/* Done with 3 interrupts: the first one primes the cache and the+*2followingonesmeasuretheinterval.Theprecisionofthemethod+*isstilldoubtfulduetotheshortintervalsampled.+*/+static__initdatavolatileintcalibrate_steps=3;+static__initdataunsignedtbstamp;void__initprep_calibrate_decr_handler(intirq,void*dev,structpt_regs*regs){-unsignedlongfreq,divisor;-staticunsignedlongt1=0,t2=0;--if(!t1)-t1=get_dec();-elseif(!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;+unsignedlongt,freq;+intstep=--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__initmk48t59_calibrate_decr(void){-unsignedlongfreq,divisor;-unsignedlongt1,t2;+unsignedlongfreq;+unsignedlongt1;unsignedcharsave_control;longi;unsignedcharsec;
@@ -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+*whichweonlyreadthesecondscounter.nvram_read_valwrites+*theaddressbytesoneverycallandthistakesalotoftime.+*Perhapsannvram_wait_changemethodreturningatime+*stampwithaloopcountasparameterwouldbethesolution.+*/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
@@ -44,24 +65,22 @@#include<asm/8xx_immap.h>#include<asm/machdep.h>-#include"time.h"+#include<asm/time.h>voidsmp_local_timer_interrupt(structpt_regs*);/* keep track of when we need to update the rtc */-time_tlast_rtc_update=0;+time_tlast_rtc_update;externrwlock_txtime_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-unsigneddecrementer_count;/* count value for 1e6/HZ microseconds */-unsignedcount_period_num;/* 1 decrementer count equals */-unsignedcount_period_den;/* count_period_num / count_period_den us */-unsignedlonglast_tb;+unsignedtb_ticks_per_jiffy;+unsignedtb_to_us;+unsignedtb_last_stamp;+externunsignedlongwall_jiffies;/**timer_interrupt-getscalledwhenthedecrementeroverflows,*withinterruptsdisabled.
@@ -95,47 +114,47 @@}#endif /* CONFIG_SMP */-dval=get_dec();-/*-*Waitforthedecrementertochange,thenjump-*inandadddecrementer_counttoitsvalue-*(quickly,beforeitchangesagain!)-*/-while((d=get_dec())==dval)-;-asmvolatile("mftb %0":"=r"(last_tb));-/*-*Don'tplaycatchupbetweenthecalltotime_init()-*andsti()ininit/main.c.-*-*Thisalsomeansifwe'redelayedfor>HZ-*welosethoseticks.Ifwe'redelayedfor>HZ-*thenwehavesomethingwronganyway,though.-*-*--Cort+/* This might fail on 601 SMP systems, are there any out there ?+*TherightwaytodoitmightbetoaddaperCPUtimebasestamp+*intheperCPUinterruptstructure.Wouldthisbeacceptable?*/-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);/*-*updatethertcwhenneeded+*updatethertcwhenneeded,thisshouldbeperformedonthe+*rightfractionofasecond.Halforfullsecond?+*Fullsecondworksonmk48t59clocks,othersneedtesting.+*Notethatthisupdateisbasicallyonlyusedthrough+*theadjtimexsystemcalls.SettingtheHWclockin+*anyotherwayisa/dev/rtcanduserlandbusiness.+*Thisisstillwrongby-0.5/+1.5jiffiesbecauseofthe+*timerinterruptresolutionandpossibledelay,butherewe+*hitaquantizationlimitwhichcanonlybesolvedbyhigher+*resolutiontimersanddecouplingtimemanagementfromtimer+*interrupts.+*Weshouldhaveanrtccallthatonlysetstheminutesand+*secondslikeonInteltoavoidproblemswithnonUTCclocks.*/-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_SMPsmp_local_timer_interrupt(regs);#endif
@@ -152,46 +171,57 @@*/voiddo_gettimeofday(structtimeval*tv){-unsignedlongflags,diff;+unsignedlongflags;+unsigneddelta,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-asmvolatile("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;}voiddo_settimeofday(structtimeval*tv){unsignedlongflags;-intfrac_tick;--last_rtc_update=0;/* so the rtc gets updated soon */+inttv_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+*introducingrandomfractionalsecondoffsets.Donotattemptthe+*updatebeforethenextsecondboundary.Actually,itwillnot+*beupdateduntilSTA_UNSYNCiscleared.Notealsothat+*wedon'ttouchthedecrementersince:+*a)itwouldlosetimerinterruptsynchronizationonSMP+*b)itcouldmakeonejiffyspuriouslyshorterorlonger+*whichwouldintroduceanothersourceofuncertaintypotentially+*harmfultorelativelyshorttimers.+*Inshort,jiffiesarealwaysupdatedatregularintervals+*andit'stheclockwalltime(xtime)whichisadjustedand+*isnotalwaysamultipleof1/Hzseconds.+*/++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;}elseif(!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+*frequencygivingresolutionofafewtensofnanosecondsisquitenice.+*Itmakesthiscomputationveryprecise(27-28bitstypically)which+*isoptimisticconsideringthestabilityofmostprocessorclock+*oscillatorsandtheprecisionwithwhichthetimebasefrequency+*ismeasuredbutdoesnotharm.+*/+unsignedmulhwu_scale_factor(unsignedinscale,unsignedoutscale){+unsignedmlt=0,tmp,err;+/* No concern for performance, it's done once: use a stupid+*butsafeandcompactmethodtofindthemultiplier.+*/+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.+*Asideeffectofthisisthatifoutscaleistoolarge+*thereturnedvaluewillbezero.+*Manycornercaseshavebeencheckedandseemtowork,+*somemighthavebeenforgotteninthetesthowever.+*Theprecisionfortypicalvalues(outscaleis1million),+*inscaleisbetweenafewmillionstoafewtensof+*millionsis27-28bits,whichisoptimisticaboutthe+*qualityof99.99%CPUclockoscillators(andtheprecision+*withwhichthefrequencyismeasuredatbootwiththecurrent+*setup)butdoesnoharm.+*/+err=inscale*(mlt+1);+if(err<=inscale/2)mlt++;+returnmlt;+}+
===== 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
@@ -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__intconst__USE_RTC(void){+return(mfspr(SPRN_PVR)>>16)==1;+}+#else+#define __USE_RTC() 0+#endif++extern__inline__unsignedlongget_tbl(void){+unsignedlongtbl;+asmvolatile("mftb %0":"=r"(tbl));+returntbl;+}++extern__inline__unsignedlongget_rtcl(void){+unsignedlongrtcl;+asmvolatile("mfrtcl %0":"=r"(rtcl));+returnrtcl;+}++extern__inline__unsignedget_native_tbl(void){+if(__USE_RTC())+returnget_rtcl();+else+returnget_tbl();+}++/* On machines with RTC, this function can only be used safely+*afterthetimestampandfor1second.Itisonlyusedbygettimeofday+*howeversoitshouldnotmatter.+*/+extern__inline__unsignedtb_ticks_since(unsignedtstamp){+if(__USE_RTC()){+intdelta=get_rtcl()-tstamp;+returndelta<0?delta+1000000000:delta;+}else{+returnget_tbl()-tstamp;+}+}++#if 0+extern__inline__unsignedlongget_bin_rtcl(void){+unsignedlongrtcl,rtcu1,rtcu2;+asmvolatile("\+1:mfrtcu%0\n\+mfrtcl%1\n\+mfrtcu%2\n\+cmpw%0,%2\n\+bne-1b\n"+:"=r"(rtcu1),"=r"(rtcl),"=r"(rtcu2)+::"cr0");+returnrtcu2*1000000000+rtcl;+}++extern__inline__unsignedbinary_tbl(void){+if(__USE_RTC())+returnget_bin_rtcl();+else+returnget_tbl();+}+#endif++/* Use mulhwu to scale processor timebase to timeval */+#define mulhwu(x,y) \+({unsignedz;asm("mulhwu %0,%1,%2":"=r"(z):"r"(x),"r"(y));z;})++unsignedmulhwu_scale_factor(unsigned,unsigned);
From: Benjamin Herrenschmidt <hidden> Date: 2000-08-03 11:14:22
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/
From: Gabriel Paubert <hidden> Date: 2000-08-03 11:25:32
On Thu, 3 Aug 2000, Benjamin Herrenschmidt wrote:
quoted
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.
quoted
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/
From: Gabriel Paubert <hidden> Date: 2000-08-03 11:45:24
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/
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/
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/
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/
From: Gabriel Paubert <hidden> Date: 2000-08-08 11:20:39
Hi Geert,
On Fri, 4 Aug 2000, Geert Uytterhoeven wrote:
quoted
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/