diff options
author | Artur Grabowski <art@cvs.openbsd.org> | 2007-03-16 09:28:39 +0000 |
---|---|---|
committer | Artur Grabowski <art@cvs.openbsd.org> | 2007-03-16 09:28:39 +0000 |
commit | 547f15bd4611ec89cc98fb3cdf82324cad510e06 (patch) | |
tree | fc37ab80f57a749f533031ed2c4562b1fcc985a7 | |
parent | a9932968b85bcf7f1a4f3e62c14d2b45164aeb48 (diff) |
Timecounters for sparc64. The cleanest and easiest timecounter
implementation this far. Uses the %tick register (as microtime was
using before).
kettenis@ ok
-rw-r--r-- | sys/arch/sparc64/include/_types.h | 3 | ||||
-rw-r--r-- | sys/arch/sparc64/sparc64/clock.c | 93 | ||||
-rw-r--r-- | sys/arch/sparc64/sparc64/intr.c | 6 |
3 files changed, 44 insertions, 58 deletions
diff --git a/sys/arch/sparc64/include/_types.h b/sys/arch/sparc64/include/_types.h index cf78a2211f7..a4a1303a990 100644 --- a/sys/arch/sparc64/include/_types.h +++ b/sys/arch/sparc64/include/_types.h @@ -1,4 +1,4 @@ -/* $OpenBSD: _types.h,v 1.2 2007/02/03 20:08:50 miod Exp $ */ +/* $OpenBSD: _types.h,v 1.3 2007/03/16 09:28:38 art Exp $ */ /*- * Copyright (c) 1990, 1993 @@ -124,5 +124,6 @@ typedef void * __wctype_t; #define __HAVE_DEVICE_REGISTER #define __HAVE_GENERIC_SOFT_INTERRUPTS #define __HAVE_MUTEX +#define __HAVE_TIMECOUNTER #endif /* _SPARC64__TYPES_H_ */ diff --git a/sys/arch/sparc64/sparc64/clock.c b/sys/arch/sparc64/sparc64/clock.c index e4d6f1fb49a..986ba0f06c1 100644 --- a/sys/arch/sparc64/sparc64/clock.c +++ b/sys/arch/sparc64/sparc64/clock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clock.c,v 1.26 2006/07/01 20:05:11 kettenis Exp $ */ +/* $OpenBSD: clock.c,v 1.27 2007/03/16 09:28:38 art Exp $ */ /* $NetBSD: clock.c,v 1.41 2001/07/24 19:29:25 eeh Exp $ */ /* @@ -74,6 +74,7 @@ #include <sys/gmon.h> #endif #include <sys/sched.h> +#include <sys/timetc.h> #include <uvm/uvm_extern.h> @@ -96,7 +97,6 @@ #include <sparc64/dev/ebusvar.h> #include <sparc64/dev/fhcvar.h> -static u_int64_t lasttick; extern u_int64_t cpu_clockrate; struct rtc_info { @@ -114,6 +114,12 @@ struct cfdriver clock_cd = { NULL, "clock", DV_DULL }; +u_int tick_get_timecount(struct timecounter *); + +struct timecounter tick_timecounter = { + tick_get_timecount, NULL, ~0u, 0, "tick", 0, NULL +}; + /* * Statistics clock interval and variance, in usec. Variance must be a * power of two. Since this gives us an even number, not an odd number, @@ -665,7 +671,6 @@ void cpu_initclocks() { int statint, minint; - static u_int64_t start_time; #ifdef DEBUG extern int intrdebug; #endif @@ -689,21 +694,10 @@ cpu_initclocks() if (!cpu_clockrate) /* Default to 200MHz clock XXXXX */ cpu_clockrate = 200000000; - - /* - * Calculate the starting %tick value. We set that to the same - * as time, scaled for the CPU clockrate. This gets nasty, but - * we can handle it. time.tv_usec is in microseconds. - * cpu_clockrate is in MHz. - */ - start_time = time.tv_sec * cpu_clockrate; - /* Now fine tune the usecs */ - start_time += cpu_clockrate / 1000000 * time.tv_usec; - - /* Initialize the %tick register */ - lasttick = start_time; - __asm __volatile("wrpr %0, 0, %%tick" : : "r" (start_time)); + tick_timecounter.tc_frequency = cpu_clockrate; + tc_init(&tick_timecounter); + /* * Now handle machines w/o counter-timers. */ @@ -818,7 +812,7 @@ clockintr(cap) t = tick() & TICK_TICKS; if (!tick_base) { - tick_base = (time.tv_sec * 1000000LL + time.tv_usec) + tick_base = (time_second * 1000000LL + time.tv_usec) * 1000000LL / cpu_clockrate; tick_base -= t; } else if (clockcheck) { @@ -841,8 +835,6 @@ clockintr(cap) /* Let locore.s clear the interrupt for us. */ hardclock((struct clockframe *)cap); - lasttick = tick() & TICK_TICKS; - level10.ih_count.ec_count++; return (1); @@ -865,8 +857,6 @@ tickintr(cap) hardclock((struct clockframe *)cap); s = splhigh(); - __asm __volatile("rd %%tick, %0" : "=r" (lasttick) :); - lasttick &= TICK_TICKS; /* Reset the interrupt */ next_tick(tick_increment); level0.ih_count.ec_count++; @@ -945,6 +935,8 @@ inittodr(base) { int badbase = 0, waszero = base == 0; char *bad = NULL; + struct timeval tv; + struct timespec ts; if (base < 5 * SECYR) { /* @@ -958,32 +950,39 @@ inittodr(base) badbase = 1; } - if (todr_handle && - (todr_gettime(todr_handle, (struct timeval *)&time) != 0 || - time.tv_sec == 0)) { + if (todr_handle && (todr_gettime(todr_handle, &tv) != 0 || + tv.tv_sec == 0)) { /* * Believe the time in the file system for lack of * anything better, resetting the clock. */ bad = "WARNING: bad date in battery clock"; - time.tv_sec = base; + tv.tv_sec = base; + tv.tv_usec = 0; if (!badbase) resettodr(); } else { - int deltat = time.tv_sec - base; + int deltat = tv.tv_sec - base; sparc_clock_time_is_ok = 1; if (deltat < 0) deltat = -deltat; - if (waszero || deltat < 2 * SECDAY) - return; + if (!(waszero || deltat < 2 * SECDAY)) { #ifndef SMALL_KERNEL - printf("WARNING: clock %s %ld days", - time.tv_sec < base ? "lost" : "gained", deltat / SECDAY); - bad = ""; + printf("WARNING: clock %s %ld days", + tv.tv_sec < base ? "lost" : "gained", deltat / SECDAY); + bad = ""; + } #endif } + +printf("setting time to: %d\n", tv.tv_sec); + + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000; + tc_setclock(&ts); + if (bad) { printf("%s", bad); printf(" -- CHECK AND RESET THE DATE!\n"); @@ -999,13 +998,15 @@ inittodr(base) void resettodr() { + struct timeval tv; - if (time.tv_sec == 0) + if (time_second == 0) return; + microtime(&tv); + sparc_clock_time_is_ok = 1; - if (todr_handle == 0 || - todr_settime(todr_handle, (struct timeval *)&time) != 0) + if (todr_handle == 0 || todr_settime(todr_handle, &tv) != 0) printf("Cannot set time in time-of-day clock\n"); } @@ -1140,28 +1141,12 @@ rtc_setcal(handle, v) #define USECPERSEC 1000000 -void -microtime(tvp) - struct timeval *tvp; +u_int +tick_get_timecount(struct timecounter *tc) { - 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; - - while (tvp->tv_usec >= USECPERSEC) { - tvp->tv_sec++; - tvp->tv_usec -= USECPERSEC; - } + return (tick & ~0u); } diff --git a/sys/arch/sparc64/sparc64/intr.c b/sys/arch/sparc64/sparc64/intr.c index d4121d0cca1..861699210bb 100644 --- a/sys/arch/sparc64/sparc64/intr.c +++ b/sys/arch/sparc64/sparc64/intr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: intr.c,v 1.23 2005/04/26 18:54:39 miod Exp $ */ +/* $OpenBSD: intr.c,v 1.24 2007/03/16 09:28:38 art Exp $ */ /* $NetBSD: intr.c,v 1.39 2001/07/19 23:38:11 eeh Exp $ */ /* @@ -105,12 +105,12 @@ strayintr(fp, vectored) (unsigned long long)fp->tf_npc, fp->tf_tstate>>TSTATE_PSTATE_SHIFT, PSTATE_BITS, vectored); - timesince = time.tv_sec - straytime; + timesince = time_second - straytime; if (timesince <= 10) { if (++nstray > 500) panic("crazy interrupts"); } else { - straytime = time.tv_sec; + straytime = time_second; nstray = 1; } #ifdef DDB |