summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArtur Grabowski <art@cvs.openbsd.org>2007-03-16 09:28:39 +0000
committerArtur Grabowski <art@cvs.openbsd.org>2007-03-16 09:28:39 +0000
commit547f15bd4611ec89cc98fb3cdf82324cad510e06 (patch)
treefc37ab80f57a749f533031ed2c4562b1fcc985a7
parenta9932968b85bcf7f1a4f3e62c14d2b45164aeb48 (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.h3
-rw-r--r--sys/arch/sparc64/sparc64/clock.c93
-rw-r--r--sys/arch/sparc64/sparc64/intr.c6
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