summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorArtur Grabowski <art@cvs.openbsd.org>2007-04-23 10:07:44 +0000
committerArtur Grabowski <art@cvs.openbsd.org>2007-04-23 10:07:44 +0000
commitb41a3dfa9ac078d78d5e49d89aa1b8c88bd26b8e (patch)
tree077e3660edff7dc47ef9d17f7e9f540955f173d8 /sys/arch
parent210b61e6bccd8bf072cc37c00135115aa80a1891 (diff)
Switch alpha to timecounters.
We use rpcc for the clock. We don't try to get the frequency from the hwrpb, since from experience we know that it's very unreliable and can be several % off from the real frequency. Instead we calibrate the timecounter frequency by using the clock device and count the number of cycles between two second ticks of the clocks. This is not perfect, but still much better than what we had before. We'll have to add an i8254 clock for MP though. miod@ ok
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/alpha/alpha/clock.c72
-rw-r--r--sys/arch/alpha/alpha/machdep.c34
-rw-r--r--sys/arch/alpha/include/_types.h3
3 files changed, 58 insertions, 51 deletions
diff --git a/sys/arch/alpha/alpha/clock.c b/sys/arch/alpha/alpha/clock.c
index e828b9430ac..3813b19a840 100644
--- a/sys/arch/alpha/alpha/clock.c
+++ b/sys/arch/alpha/alpha/clock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clock.c,v 1.14 2004/06/28 02:28:42 aaron Exp $ */
+/* $OpenBSD: clock.c,v 1.15 2007/04/23 10:07:43 art Exp $ */
/* $NetBSD: clock.c,v 1.29 2000/06/05 21:47:10 thorpej Exp $ */
/*
@@ -44,6 +44,7 @@
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/evcount.h>
+#include <sys/timetc.h>
#include <dev/clock_subr.h>
@@ -75,6 +76,11 @@ int clockinitted;
struct evcount clk_count;
int clk_irq = 0;
+u_int rpcc_get_timecount(struct timecounter *);
+struct timecounter rpcc_timecounter = {
+ rpcc_get_timecount, NULL, ~0u, 0, "rpcc", 0, NULL
+};
+
void
clockattach(dev, fns)
struct device *dev;
@@ -110,20 +116,17 @@ clockattach(dev, fns)
* are no other timers available.
*/
void
-cpu_initclocks()
+cpu_initclocks(void)
{
+ u_int32_t cycles_per_sec;
+ struct clocktime ct;
+ u_int32_t first_rpcc, second_rpcc; /* only lower 32 bits are valid */
+ int first_sec;
+
if (clockfns == NULL)
panic("cpu_initclocks: no clock attached");
tick = 1000000 / hz; /* number of microseconds between interrupts */
- tickfix = 1000000 - (hz * tick);
- if (tickfix) {
- int ftp;
-
- ftp = min(ffs(tickfix), ffs(hz));
- tickfix >>= (ftp - 1);
- tickfixinterval = hz >> (ftp - 1);
- }
/*
* Establish the clock interrupt; it's a special case.
@@ -146,6 +149,30 @@ cpu_initclocks()
* Get the clock started.
*/
(*clockfns->cf_init)(clockdev);
+
+ /*
+ * Calibrate the cycle counter frequency.
+ */
+ (*clockfns->cf_get)(clockdev, 0, &ct);
+ first_sec = ct.sec;
+
+ /* Let the clock tick one second. */
+ do {
+ first_rpcc = alpha_rpcc();
+ (*clockfns->cf_get)(clockdev, 0, &ct);
+ } while (ct.sec == first_sec);
+ first_sec = ct.sec;
+ /* Let the clock tick one more second. */
+ do {
+ second_rpcc = alpha_rpcc();
+ (*clockfns->cf_get)(clockdev, 0, &ct);
+ } while (ct.sec == first_sec);
+
+ cycles_per_sec = second_rpcc - first_rpcc;
+
+ rpcc_timecounter.tc_frequency = cycles_per_sec;
+
+ tc_init(&rpcc_timecounter);
}
/*
@@ -167,14 +194,16 @@ setstatclockrate(newhz)
* and the time of year clock (if any) provides the rest.
*/
void
-inittodr(base)
- time_t base;
+inittodr(time_t base)
{
struct clocktime ct;
int year;
struct clock_ymdhms dt;
time_t deltat;
int badbase;
+ struct timespec ts;
+
+ ts.tv_sec = ts.tv_nsec = 0;
if (base < (MINYEAR-1970)*SECYR) {
printf("WARNING: preposterous time in file system");
@@ -202,7 +231,7 @@ inittodr(base)
* Believe the time in the file system for lack of
* anything better, resetting the TODR.
*/
- time.tv_sec = base;
+ ts.tv_sec = base;
if (!badbase) {
printf("WARNING: preposterous clock chip time\n");
resettodr();
@@ -216,9 +245,9 @@ inittodr(base)
dt.dt_hour = ct.hour;
dt.dt_min = ct.min;
dt.dt_sec = ct.sec;
- time.tv_sec = clock_ymdhms_to_secs(&dt);
+ ts.tv_sec = clock_ymdhms_to_secs(&dt);
#ifdef DEBUG
- printf("=>%ld (%d)\n", time.tv_sec, base);
+ printf("=>%ld (%d)\n", ts.tv_sec, base);
#endif
if (!badbase) {
@@ -226,15 +255,16 @@ inittodr(base)
* See if we gained/lost two or more days;
* if so, assume something is amiss.
*/
- deltat = time.tv_sec - base;
+ deltat = ts.tv_sec - base;
if (deltat < 0)
deltat = -deltat;
if (deltat < 2 * SECDAY)
return;
printf("WARNING: clock %s %ld days",
- time.tv_sec < base ? "lost" : "gained",
+ ts.tv_sec < base ? "lost" : "gained",
(long)deltat / SECDAY);
}
+ tc_setclock(&ts);
bad:
printf(" -- CHECK AND RESET THE DATE!\n");
}
@@ -255,7 +285,7 @@ resettodr()
if (!clockinitted)
return;
- clock_secs_to_ymdhms(time.tv_sec, &dt);
+ clock_secs_to_ymdhms(time_second, &dt);
/* rt clock wants 2 digits */
ct.year = (dt.dt_year - UNIX_YEAR_OFFSET) % 100;
@@ -272,3 +302,9 @@ resettodr()
(*clockfns->cf_set)(clockdev, &ct);
}
+
+u_int
+rpcc_get_timecount(struct timecounter *tc)
+{
+ return alpha_rpcc();
+}
diff --git a/sys/arch/alpha/alpha/machdep.c b/sys/arch/alpha/alpha/machdep.c
index d7d2d43255c..3d600589dd7 100644
--- a/sys/arch/alpha/alpha/machdep.c
+++ b/sys/arch/alpha/alpha/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.106 2007/04/18 16:53:19 martin Exp $ */
+/* $OpenBSD: machdep.c,v 1.107 2007/04/23 10:07:43 art Exp $ */
/* $NetBSD: machdep.c,v 1.210 2000/06/01 17:12:38 thorpej Exp $ */
/*-
@@ -96,6 +96,7 @@
#ifdef SYSVMSG
#include <sys/msg.h>
#endif
+#include <sys/timetc.h>
#include <sys/mount.h>
#include <sys/syscallargs.h>
@@ -2007,37 +2008,6 @@ remrunqueue(p)
}
/*
- * Return the best possible estimate of the time in the timeval
- * to which tvp points. Unfortunately, we can't read the hardware registers.
- * We guarantee that the time will be greater than the value obtained by a
- * previous call.
- */
-void
-microtime(tvp)
- register struct timeval *tvp;
-{
- int s = splclock();
- static struct timeval lasttime;
-
- *tvp = time;
-#ifdef notdef
- tvp->tv_usec += clkread();
- while (tvp->tv_usec >= 1000000) {
- tvp->tv_sec++;
- tvp->tv_usec -= 1000000;
- }
-#endif
- if (tvp->tv_sec == lasttime.tv_sec &&
- tvp->tv_usec <= lasttime.tv_usec &&
- (tvp->tv_usec = lasttime.tv_usec + 1) >= 1000000) {
- tvp->tv_sec++;
- tvp->tv_usec -= 1000000;
- }
- lasttime = *tvp;
- splx(s);
-}
-
-/*
* Wait "n" microseconds.
*/
void
diff --git a/sys/arch/alpha/include/_types.h b/sys/arch/alpha/include/_types.h
index 6f005758e56..480e591a94a 100644
--- a/sys/arch/alpha/include/_types.h
+++ b/sys/arch/alpha/include/_types.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: _types.h,v 1.3 2007/04/21 21:37:09 martin Exp $ */
+/* $OpenBSD: _types.h,v 1.4 2007/04/23 10:07:43 art Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -122,5 +122,6 @@ typedef void * __wctype_t;
#define __HAVE_DEVICE_REGISTER
#define __HAVE_CPUINFO
#define __HAVE_GENERIC_SOFT_INTERRUPTS
+#define __HAVE_TIMECOUNTER
#endif /* _ALPHA__TYPES_H_ */