diff options
-rw-r--r-- | sys/arch/sparc64/sparc64/clock.c | 87 | ||||
-rw-r--r-- | sys/arch/sparc64/sparc64/locore.s | 160 |
2 files changed, 49 insertions, 198 deletions
diff --git a/sys/arch/sparc64/sparc64/clock.c b/sys/arch/sparc64/sparc64/clock.c index 9ffd293bf1b..ff18638575a 100644 --- a/sys/arch/sparc64/sparc64/clock.c +++ b/sys/arch/sparc64/sparc64/clock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clock.c,v 1.10 2002/03/14 03:16:01 millert Exp $ */ +/* $OpenBSD: clock.c,v 1.11 2002/04/03 17:22:40 jason Exp $ */ /* $NetBSD: clock.c,v 1.41 2001/07/24 19:29:25 eeh Exp $ */ /* @@ -95,6 +95,7 @@ #include <sparc64/dev/ebusreg.h> #include <sparc64/dev/ebusvar.h> +static u_int64_t lasttick; extern u_int64_t cpu_clockrate; struct rtc_info { @@ -580,45 +581,6 @@ timerattach(parent, self, aux) (u_long)level10.ih_number, (u_long)level14.ih_number); -#if 0 - cnt = &(timerreg_4u.t_timer[0].t_count); - lim = &(timerreg_4u.t_timer[0].t_limit); - - /* - * Calibrate delay() by tweaking the magic constant - * until a delay(100) actually reads (at least) 100 us - * on the clock. Since we're using the %tick register - * which should be running at exactly the CPU clock rate, it - * has a period of somewhere between 7ns and 3ns. - */ - -#ifdef DEBUG - printf("Delay calibrarion....\n"); -#endif - for (timerblurb = 1; timerblurb > 0; timerblurb++) { - volatile int discard; - register int t0, t1; - - /* Reset counter register by writing some large limit value */ - discard = *lim; - *lim = tmr_ustolim(TMR_MASK-1); - - t0 = *cnt; - delay(100); - t1 = *cnt; - - if (t1 & TMR_LIMIT) - panic("delay calibration"); - - t0 = (t0 >> TMR_SHIFT) & TMR_MASK; - t1 = (t1 >> TMR_SHIFT) & TMR_MASK; - - if (t1 >= t0 + 100) - break; - } - - printf(" delay constant %d\n", timerblurb); -#endif printf("\n"); timerok = 1; } @@ -710,6 +672,7 @@ cpu_initclocks() start_time += cpu_clockrate / 1000000 * time.tv_usec; /* Initialize the %tick register */ + lasttick = start_time; #ifdef __arch64__ __asm __volatile("wrpr %0, 0, %%tick" : : "r" (start_time)); #else @@ -878,6 +841,8 @@ tickintr(cap) setsoftint(); s = splhigh(); + __asm __volatile("rd %%tick, %0" : "=r" (lasttick) :); + lasttick &= TICK_TICKS; /* Reset the interrupt */ next_tick(tick_increment); splx(s); @@ -1138,3 +1103,45 @@ rtc_setcal(handle, v) return (EOPNOTSUPP); } +#define USECPERSEC 1000000 + +void +microtime(tvp) + struct timeval *tvp; +{ + if (timerreg_4u.t_timer == NULL) { + int s; + u_int64_t tick; + + s = splhigh(); + __asm __volatile("rd %%tick, %0" : "=r" (tick) :); + tick &= TICK_TICKS; + tick -= lasttick; + tvp->tv_sec = time.tv_sec; + tvp->tv_usec = time.tv_usec; + splx(s); + + tick = (tick * USECPERSEC) / cpu_clockrate; + + tvp->tv_sec += tick / USECPERSEC; + tvp->tv_usec += tick % USECPERSEC; + } else { + struct timeval t1, t2; + int64_t t_tick; + + do { + + t1 = time; + t_tick = timerreg_4u.t_timer->t_count; + t2 = time; + } while (t1.tv_sec != t2.tv_sec || t1.tv_usec != t2.tv_usec); + + tvp->tv_sec = t1.tv_sec; + tvp->tv_usec = t1.tv_usec + t_tick; + } + + while (tvp->tv_usec >= USECPERSEC) { + tvp->tv_sec++; + tvp->tv_usec -= USECPERSEC; + } +} diff --git a/sys/arch/sparc64/sparc64/locore.s b/sys/arch/sparc64/sparc64/locore.s index d3f6ae48ea9..0a3870880a5 100644 --- a/sys/arch/sparc64/sparc64/locore.s +++ b/sys/arch/sparc64/sparc64/locore.s @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.s,v 1.12 2002/03/14 01:26:45 millert Exp $ */ +/* $OpenBSD: locore.s,v 1.13 2002/04/03 17:22:41 jason Exp $ */ /* $NetBSD: locore.s,v 1.137 2001/08/13 06:10:10 jdolecek Exp $ */ /* @@ -70,7 +70,6 @@ #define PMAP_PHYS_PAGE /* Use phys ASIs for pmap copy/zero */ #undef DCACHE_BUG /* Flush D$ around ASI_PHYS accesses */ #undef NO_TSB /* Don't use TSB */ -#define TICK_IS_TIME /* Keep %tick synchronized with time */ #undef SCHED_DEBUG #include "assym.h" @@ -11825,34 +11824,9 @@ ENTRY(random) retl st %o0, [%o5 + %lo(randseed)] -/* - * void microtime(struct timeval *tv) - * - * LBL's sparc bsd 'microtime': We don't need to spl (so this routine - * can be a leaf routine) and we don't keep a 'last' timeval (there - * can't be two calls to this routine in a microsecond). This seems to - * be about 20 times faster than the Sun code on an SS-2. - vj - * - * Read time values from slowest-changing to fastest-changing, - * then re-read out to slowest. If the values read before - * the innermost match those read after, the innermost value - * is consistent with the outer values. If not, it may not - * be and we must retry. Typically this loop runs only once; - * occasionally it runs twice, and only rarely does it run longer. - * - * If we used the %tick register we could go into the nano-seconds, - * and it must run for at least 10 years according to the v9 spec. - * - * For some insane reason timeval structure members are `long's so - * we need to change this code depending on the memory model. - * - * NB: if somehow time was 128-bit aligned we could use an atomic - * quad load to read it in and not bother de-bouncing it. - */ #define MICROPERSEC (1000000) - .data - .align 8 + .align 16 .globl _C_LABEL(cpu_clockrate) _C_LABEL(cpu_clockrate): !! Pretend we have a 200MHz clock -- cpu_attach will fix this @@ -11861,113 +11835,6 @@ _C_LABEL(cpu_clockrate): .xword 0 .text -ENTRY(microtime) - sethi %hi(timerreg_4u), %g3 - sethi %hi(_C_LABEL(time)), %g2 - LDPTR [%g3+%lo(timerreg_4u)], %g3 ! usec counter - brz,pn %g3, microtick ! If we have no counter-timer use %tick -2: - !! NB: if we could guarantee 128-bit alignment of these values we could do an atomic read - LDPTR [%g2+%lo(_C_LABEL(time))], %o2 ! time.tv_sec & time.tv_usec - LDPTR [%g2+%lo(_C_LABEL(time)+PTRSZ)], %o3 ! time.tv_sec & time.tv_usec - ldx [%g3], %o4 ! Load usec timer valuse - LDPTR [%g2+%lo(_C_LABEL(time))], %g1 ! see if time values changed - LDPTR [%g2+%lo(_C_LABEL(time)+PTRSZ)], %g5 ! see if time values changed - cmp %g1, %o2 - bne 2b ! if time.tv_sec changed - cmp %g5, %o3 - bne 2b ! if time.tv_usec changed - add %o4, %o3, %o3 ! Our timers have 1usec resolution - - set MICROPERSEC, %o5 ! normalize usec value - sub %o3, %o5, %o5 ! Did we overflow? - brlz,pn %o5, 4f - nop - add %o2, 1, %o2 ! overflow - mov %o5, %o3 -4: - STPTR %o2, [%o0] ! (should be able to std here) - retl - STPTR %o3, [%o0+PTRSZ] - -microtick: -#ifndef TICK_IS_TIME -/* - * The following code only works if %tick is reset each interrupt. - */ -2: - !! NB: if we could guarantee 128-bit alignment of these values we could do an atomic read - LDPTR [%g2+%lo(_C_LABEL(time))], %o2 ! time.tv_sec & time.tv_usec - LDPTR [%g2+%lo(_C_LABEL(time)+PTRSZ)], %o3 ! time.tv_sec & time.tv_usec - rdpr %tick, %o4 ! Load usec timer value - LDPTR [%g2+%lo(_C_LABEL(time))], %g1 ! see if time values changed - LDPTR [%g2+%lo(_C_LABEL(time)+PTRSZ)], %g5 ! see if time values changed - cmp %g1, %o2 - bne 2b ! if time.tv_sec changed - cmp %g5, %o3 - bne 2b ! if time.tv_usec changed - sethi %hi(_C_LABEL(cpu_clockrate)), %g1 - ldx [%g1 + %lo(_C_LABEL(cpu_clockrate) + 8)], %o1 - sethi %hi(MICROPERSEC), %o5 - brnz,pt %o1, 3f - or %o5, %lo(MICROPERSEC), %o5 - - !! Calculate ticks/usec - ldx [%g1 + %lo(_C_LABEL(cpu_clockrate))], %o1 ! No, we need to calculate it - udivx %o1, %o5, %o1 - stx %o1, [%g1 + %lo(_C_LABEL(cpu_clockrate) + 8)] ! Save it so we don't need to divide again -3: - udivx %o4, %o1, %o4 ! Convert to usec - add %o4, %o3, %o3 - - sub %o3, %o5, %o5 ! Did we overflow? - brlz,pn %o5, 4f - nop - add %o2, 1, %o2 ! overflow - mov %o5, %o3 -4: - STPTR %o2, [%o0] ! (should be able to std here) - retl - STPTR %o3, [%o0+PTRSZ] -#else -/* - * The following code only works if %tick is synchronized with time. - */ -2: - LDPTR [%g2+%lo(_C_LABEL(time))], %o2 ! time.tv_sec & time.tv_usec - LDPTR [%g2+%lo(_C_LABEL(time)+PTRSZ)], %o3 ! time.tv_sec & time.tv_usec - rdpr %tick, %o4 ! Load usec timer value - LDPTR [%g2+%lo(_C_LABEL(time))], %g1 ! see if time values changed - LDPTR [%g2+%lo(_C_LABEL(time)+PTRSZ)], %g5 ! see if time values changed - cmp %g1, %o2 - bne 2b ! if time.tv_sec changed - cmp %g5, %o3 - bne 2b ! if time.tv_usec changed - - sethi %hi(_C_LABEL(cpu_clockrate)), %o1 - ldx [%o1 + %lo(_C_LABEL(cpu_clockrate) + 8)], %g1 ! Get scale factor - sethi %hi(MICROPERSEC), %o5 - brnz,pt %g1, 1f ! Already scaled? - or %o5, %lo(MICROPERSEC), %o5 - - !! Calculate ticks/usec - ldx [%o1 + %lo(_C_LABEL(cpu_clockrate))], %g1 ! No, we need to calculate it - udivx %g1, %o5, %g1 ! Hz / 10^6 = MHz - stx %g1, [%o1 + %lo(_C_LABEL(cpu_clockrate) + 8)] ! Save it so we don't need to divide again -1: - - STPTR %o2, [%o0] ! Store seconds. - udivx %o4, %g1, %o4 ! Scale it: ticks / MHz = usec - - udivx %o4, %o5, %o2 ! Now %o2 has seconds - - mulx %o2, %o5, %o5 ! Now calculate usecs -- damn no remainder insn - sub %o4, %o5, %o1 ! %o1 has the remainder - - retl - STPTR %o1, [%o0+PTRSZ] ! Save time_t low word -#endif - /* * delay function * @@ -11982,7 +11849,6 @@ microtick: * */ ENTRY(delay) ! %o0 = n -#if 1 rdpr %tick, %o1 ! Take timer snapshot sethi %hi(_C_LABEL(cpu_clockrate)), %o2 sethi %hi(MICROPERSEC), %o3 @@ -12008,29 +11874,7 @@ ENTRY(delay) ! %o0 = n retl nop -#else -/* This code only works if %tick does not wrap */ - rdpr %tick, %g1 ! Take timer snapshot - sethi %hi(_C_LABEL(cpu_clockrate)), %g2 - sethi %hi(MICROPERSEC), %o2 - ldx [%g2 + %lo(_C_LABEL(cpu_clockrate))], %g2 ! Get scale factor - or %o2, %lo(MICROPERSEC), %o2 -! sethi %hi(_C_LABEL(timerblurb), %o5 ! This is if we plan to tune the clock -! ld [%o5 + %lo(_C_LABEL(timerblurb))], %o5 ! with respect to the counter/timer - mulx %o0, %g2, %g2 ! Scale it: (usec * Hz) / 1 x 10^6 = ticks - udivx %g2, %o2, %g2 - add %g1, %g2, %g2 -! add %o5, %g2, %g2 5, %g2, %g2 ! But this gets complicated - rdpr %tick, %g1 ! Top of next itr - mov %g1, %g1 ! Erratum 50 -1: - cmp %g1, %g2 - bl,a,pn %xcc, 1b ! Done? - rdpr %tick, %g1 - retl - nop -#endif /* * If something's wrong with the standard setup do this stupid loop * calibrated for a 143MHz processor. |