summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/sparc64/sparc64/clock.c87
-rw-r--r--sys/arch/sparc64/sparc64/locore.s160
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.